Adoird build migration and update
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
26
mih_ui/android/build/macos/SourcePackages/firebase_auth-6.5.4/README.md
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
[<img src="https://raw.githubusercontent.com/firebase/flutterfire/main/.github/images/flutter_favorite.png" width="200" />](https://flutter.dev/docs/development/packages-and-plugins/favorites)
|
||||
|
||||
# Firebase Auth for Flutter
|
||||
[](https://pub.dev/packages/firebase_auth)
|
||||
|
||||
A Flutter plugin to use the [Firebase Authentication API](https://firebase.google.com/products/auth/).
|
||||
|
||||
To learn more about Firebase Auth, please visit the [Firebase website](https://firebase.google.com/products/auth)
|
||||
|
||||
## Getting Started
|
||||
|
||||
To get started with Firebase Auth for Flutter, please [see the documentation](https://firebase.google.com/docs/auth/flutter/start).
|
||||
|
||||
## Usage
|
||||
|
||||
To use this plugin, please visit the [Authentication Usage documentation](https://firebase.google.com/docs/auth/flutter/manage-users)
|
||||
|
||||
## Issues and feedback
|
||||
|
||||
Please file FlutterFire specific issues, bugs, or feature requests in our [issue tracker](https://github.com/firebase/flutterfire/issues/new).
|
||||
|
||||
Plugin issues that are not specific to FlutterFire can be filed in the [Flutter issue tracker](https://github.com/flutter/flutter/issues/new).
|
||||
|
||||
To contribute a change to this plugin,
|
||||
please review our [contribution guide](https://github.com/firebase/flutterfire/blob/main/CONTRIBUTING.md)
|
||||
and open a [pull request](https://github.com/firebase/flutterfire/pulls).
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
group 'io.flutter.plugins.firebase.auth'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
def firebaseCoreProject = findProject(':firebase_core')
|
||||
if (firebaseCoreProject == null) {
|
||||
throw new GradleException('Could not find the firebase_core FlutterFire plugin, have you added it as a dependency in your pubspec?')
|
||||
} else if (!firebaseCoreProject.properties['FirebaseSDKVersion']) {
|
||||
throw new GradleException('A newer version of the firebase_core FlutterFire plugin is required, please update your firebase_core pubspec dependency.')
|
||||
}
|
||||
|
||||
def getRootProjectExtOrCoreProperty(name, firebaseCoreProject) {
|
||||
if (!rootProject.ext.has('FlutterFire')) return firebaseCoreProject.properties[name]
|
||||
if (!rootProject.ext.get('FlutterFire')[name]) return firebaseCoreProject.properties[name]
|
||||
return rootProject.ext.get('FlutterFire').get(name)
|
||||
}
|
||||
|
||||
android {
|
||||
// Conditional for compatibility with AGP <4.2.
|
||||
if (project.android.hasProperty("namespace")) {
|
||||
namespace 'io.flutter.plugins.firebase.auth'
|
||||
}
|
||||
|
||||
compileSdkVersion 34
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 23
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.toVersion(17)
|
||||
targetCompatibility JavaVersion.toVersion(17)
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
buildConfig true
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
disable 'InvalidPackage'
|
||||
}
|
||||
dependencies {
|
||||
api firebaseCoreProject
|
||||
implementation platform("com.google.firebase:firebase-bom:${getRootProjectExtOrCoreProperty("FirebaseSDKVersion", firebaseCoreProject)}")
|
||||
implementation 'com.google.firebase:firebase-auth'
|
||||
implementation 'androidx.annotation:annotation:1.7.0'
|
||||
}
|
||||
}
|
||||
|
||||
apply from: file("./user-agent.gradle")
|
||||
|
|
@ -0,0 +1 @@
|
|||
org.gradle.jvmargs=-Xmx1536M
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
rootProject.name = 'firebase_auth'
|
||||
|
||||
pluginManagement {
|
||||
plugins {
|
||||
id "com.android.application" version "8.3.0"
|
||||
id "com.android.library" version "8.3.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="io.flutter.plugins.firebase.auth">
|
||||
<application>
|
||||
<service android:name="com.google.firebase.components.ComponentDiscoveryService">
|
||||
<meta-data android:name="com.google.firebase.components:io.flutter.plugins.firebase.auth.FlutterFirebaseAuthRegistrar"
|
||||
android:value="com.google.firebase.components.ComponentRegistrar" />
|
||||
</service>
|
||||
</application>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 2022, the Chromium project authors. Please see the AUTHORS file
|
||||
* for details. All rights reserved. Use of this source code is governed by a
|
||||
* BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package io.flutter.plugins.firebase.auth;
|
||||
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.auth.FirebaseAuth.AuthStateListener;
|
||||
import com.google.firebase.auth.FirebaseUser;
|
||||
import io.flutter.plugin.common.EventChannel.EventSink;
|
||||
import io.flutter.plugin.common.EventChannel.StreamHandler;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class AuthStateChannelStreamHandler implements StreamHandler {
|
||||
|
||||
private final FirebaseAuth firebaseAuth;
|
||||
private AuthStateListener authStateListener;
|
||||
|
||||
public AuthStateChannelStreamHandler(FirebaseAuth firebaseAuth) {
|
||||
this.firebaseAuth = firebaseAuth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListen(Object arguments, EventSink events) {
|
||||
Map<String, Object> event = new HashMap<>();
|
||||
event.put(Constants.APP_NAME, firebaseAuth.getApp().getName());
|
||||
|
||||
final AtomicBoolean initialAuthState = new AtomicBoolean(true);
|
||||
|
||||
authStateListener =
|
||||
auth -> {
|
||||
if (initialAuthState.get()) {
|
||||
initialAuthState.set(false);
|
||||
return;
|
||||
}
|
||||
|
||||
FirebaseUser user = auth.getCurrentUser();
|
||||
|
||||
if (user == null) {
|
||||
event.put(Constants.USER, null);
|
||||
} else {
|
||||
event.put(
|
||||
Constants.USER, PigeonParser.manuallyToList(PigeonParser.parseFirebaseUser(user)));
|
||||
}
|
||||
|
||||
events.success(event);
|
||||
};
|
||||
|
||||
firebaseAuth.addAuthStateListener(authStateListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(Object arguments) {
|
||||
if (authStateListener != null) {
|
||||
firebaseAuth.removeAuthStateListener(authStateListener);
|
||||
authStateListener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright 2022, the Chromium project authors. Please see the AUTHORS file
|
||||
* for details. All rights reserved. Use of this source code is governed by a
|
||||
* BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package io.flutter.plugins.firebase.auth;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final String APP_NAME = "appName";
|
||||
|
||||
// Providers
|
||||
public static final String SIGN_IN_METHOD_PASSWORD = "password";
|
||||
public static final String SIGN_IN_METHOD_EMAIL_LINK = "emailLink";
|
||||
public static final String SIGN_IN_METHOD_FACEBOOK = "facebook.com";
|
||||
public static final String SIGN_IN_METHOD_GOOGLE = "google.com";
|
||||
public static final String SIGN_IN_METHOD_TWITTER = "twitter.com";
|
||||
public static final String SIGN_IN_METHOD_GITHUB = "github.com";
|
||||
public static final String SIGN_IN_METHOD_PHONE = "phone";
|
||||
public static final String SIGN_IN_METHOD_OAUTH = "oauth";
|
||||
public static final String SIGN_IN_METHOD_PLAY_GAMES = "playgames.google.com";
|
||||
// User
|
||||
public static final String USER = "user";
|
||||
public static final String EMAIL = "email";
|
||||
|
||||
public static final String PROVIDER_ID = "providerId";
|
||||
public static final String CREDENTIAL = "credential";
|
||||
public static final String SECRET = "secret";
|
||||
public static final String ID_TOKEN = "idToken";
|
||||
public static final String TOKEN = "token";
|
||||
public static final String ACCESS_TOKEN = "accessToken";
|
||||
public static final String RAW_NONCE = "rawNonce";
|
||||
public static final String EMAIL_LINK = "emailLink";
|
||||
public static final String VERIFICATION_ID = "verificationId";
|
||||
public static final String SMS_CODE = "smsCode";
|
||||
public static final String SIGN_IN_METHOD = "signInMethod";
|
||||
public static final String FORCE_RESENDING_TOKEN = "forceResendingToken";
|
||||
public static final String NAME = "name";
|
||||
public static final String SERVER_AUTH_CODE = "serverAuthCode";
|
||||
|
||||
// MultiFactor
|
||||
public static final String MULTI_FACTOR_HINTS = "multiFactorHints";
|
||||
public static final String MULTI_FACTOR_SESSION_ID = "multiFactorSessionId";
|
||||
public static final String MULTI_FACTOR_RESOLVER_ID = "multiFactorResolverId";
|
||||
}
|
||||
|
|
@ -0,0 +1,782 @@
|
|||
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package io.flutter.plugins.firebase.auth;
|
||||
|
||||
import static io.flutter.plugins.firebase.auth.FlutterFirebaseMultiFactor.multiFactorUserMap;
|
||||
import static io.flutter.plugins.firebase.core.FlutterFirebasePluginRegistry.registerPlugin;
|
||||
|
||||
import android.app.Activity;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.android.gms.tasks.TaskCompletionSource;
|
||||
import com.google.firebase.FirebaseApp;
|
||||
import com.google.firebase.auth.ActionCodeResult;
|
||||
import com.google.firebase.auth.AuthCredential;
|
||||
import com.google.firebase.auth.AuthResult;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.auth.FirebaseUser;
|
||||
import com.google.firebase.auth.MultiFactor;
|
||||
import com.google.firebase.auth.MultiFactorInfo;
|
||||
import com.google.firebase.auth.MultiFactorSession;
|
||||
import com.google.firebase.auth.OAuthProvider;
|
||||
import com.google.firebase.auth.PhoneMultiFactorInfo;
|
||||
import com.google.firebase.auth.SignInMethodQueryResult;
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin;
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugin.common.EventChannel;
|
||||
import io.flutter.plugin.common.EventChannel.StreamHandler;
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
import io.flutter.plugins.firebase.core.FlutterFirebaseCorePlugin;
|
||||
import io.flutter.plugins.firebase.core.FlutterFirebasePlugin;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/** Flutter plugin for Firebase Auth. */
|
||||
public class FlutterFirebaseAuthPlugin
|
||||
implements FlutterFirebasePlugin,
|
||||
FlutterPlugin,
|
||||
ActivityAware,
|
||||
GeneratedAndroidFirebaseAuth.FirebaseAuthHostApi {
|
||||
|
||||
private static final String METHOD_CHANNEL_NAME = "plugins.flutter.io/firebase_auth";
|
||||
|
||||
// Stores the instances of native AuthCredentials by their hashCode
|
||||
static final HashMap<Integer, AuthCredential> authCredentials = new HashMap<>();
|
||||
|
||||
@Nullable private BinaryMessenger messenger;
|
||||
|
||||
private MethodChannel channel;
|
||||
private Activity activity;
|
||||
|
||||
private final Map<EventChannel, StreamHandler> streamHandlers = new HashMap<>();
|
||||
|
||||
private final FlutterFirebaseAuthUser firebaseAuthUser = new FlutterFirebaseAuthUser();
|
||||
private final FlutterFirebaseMultiFactor firebaseMultiFactor = new FlutterFirebaseMultiFactor();
|
||||
|
||||
private final FlutterFirebaseTotpMultiFactor firebaseTotpMultiFactor =
|
||||
new FlutterFirebaseTotpMultiFactor();
|
||||
private final FlutterFirebaseTotpSecret firebaseTotpSecret = new FlutterFirebaseTotpSecret();
|
||||
|
||||
private void initInstance(BinaryMessenger messenger) {
|
||||
registerPlugin(METHOD_CHANNEL_NAME, this);
|
||||
channel = new MethodChannel(messenger, METHOD_CHANNEL_NAME);
|
||||
GeneratedAndroidFirebaseAuth.FirebaseAuthHostApi.setUp(messenger, this);
|
||||
GeneratedAndroidFirebaseAuth.FirebaseAuthUserHostApi.setUp(messenger, firebaseAuthUser);
|
||||
GeneratedAndroidFirebaseAuth.MultiFactorUserHostApi.setUp(messenger, firebaseMultiFactor);
|
||||
GeneratedAndroidFirebaseAuth.MultiFactoResolverHostApi.setUp(messenger, firebaseMultiFactor);
|
||||
GeneratedAndroidFirebaseAuth.MultiFactorTotpHostApi.setUp(messenger, firebaseTotpMultiFactor);
|
||||
GeneratedAndroidFirebaseAuth.MultiFactorTotpSecretHostApi.setUp(messenger, firebaseTotpSecret);
|
||||
|
||||
this.messenger = messenger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
|
||||
initInstance(binding.getBinaryMessenger());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
|
||||
channel.setMethodCallHandler(null);
|
||||
|
||||
assert messenger != null;
|
||||
GeneratedAndroidFirebaseAuth.FirebaseAuthHostApi.setUp(messenger, null);
|
||||
GeneratedAndroidFirebaseAuth.FirebaseAuthUserHostApi.setUp(messenger, null);
|
||||
GeneratedAndroidFirebaseAuth.MultiFactorUserHostApi.setUp(messenger, null);
|
||||
GeneratedAndroidFirebaseAuth.MultiFactoResolverHostApi.setUp(messenger, null);
|
||||
GeneratedAndroidFirebaseAuth.MultiFactorTotpHostApi.setUp(messenger, null);
|
||||
GeneratedAndroidFirebaseAuth.MultiFactorTotpSecretHostApi.setUp(messenger, null);
|
||||
|
||||
channel = null;
|
||||
messenger = null;
|
||||
|
||||
removeEventListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToActivity(ActivityPluginBinding activityPluginBinding) {
|
||||
activity = activityPluginBinding.getActivity();
|
||||
firebaseAuthUser.setActivity(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromActivityForConfigChanges() {
|
||||
activity = null;
|
||||
firebaseAuthUser.setActivity(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReattachedToActivityForConfigChanges(ActivityPluginBinding activityPluginBinding) {
|
||||
activity = activityPluginBinding.getActivity();
|
||||
firebaseAuthUser.setActivity(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromActivity() {
|
||||
activity = null;
|
||||
firebaseAuthUser.setActivity(null);
|
||||
}
|
||||
|
||||
// Only access activity with this method.
|
||||
@Nullable
|
||||
private Activity getActivity() {
|
||||
return activity;
|
||||
}
|
||||
|
||||
static FirebaseAuth getAuthFromPigeon(
|
||||
GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp pigeonApp) {
|
||||
FirebaseApp app = FirebaseApp.getInstance(pigeonApp.getAppName());
|
||||
FirebaseAuth auth = FirebaseAuth.getInstance(app);
|
||||
if (pigeonApp.getTenantId() != null) {
|
||||
auth.setTenantId(pigeonApp.getTenantId());
|
||||
}
|
||||
String customDomain = FlutterFirebaseCorePlugin.customAuthDomain.get(pigeonApp.getAppName());
|
||||
if (customDomain != null) {
|
||||
auth.setCustomAuthDomain(customDomain);
|
||||
}
|
||||
|
||||
// Auth's `getCustomAuthDomain` supersedes value from `customAuthDomain` map set by
|
||||
// `initializeApp`
|
||||
if (pigeonApp.getCustomAuthDomain() != null) {
|
||||
auth.setCustomAuthDomain(pigeonApp.getCustomAuthDomain());
|
||||
}
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerIdTokenListener(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.Result<String> result) {
|
||||
try {
|
||||
final FirebaseAuth auth = getAuthFromPigeon(app);
|
||||
final IdTokenChannelStreamHandler handler = new IdTokenChannelStreamHandler(auth);
|
||||
final String name = METHOD_CHANNEL_NAME + "/id-token/" + auth.getApp().getName();
|
||||
final EventChannel channel = new EventChannel(messenger, name);
|
||||
channel.setStreamHandler(handler);
|
||||
streamHandlers.put(channel, handler);
|
||||
result.success(name);
|
||||
} catch (Exception e) {
|
||||
result.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerAuthStateListener(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.Result<String> result) {
|
||||
try {
|
||||
final FirebaseAuth auth = getAuthFromPigeon(app);
|
||||
final AuthStateChannelStreamHandler handler = new AuthStateChannelStreamHandler(auth);
|
||||
final String name = METHOD_CHANNEL_NAME + "/auth-state/" + auth.getApp().getName();
|
||||
final EventChannel channel = new EventChannel(messenger, name);
|
||||
channel.setStreamHandler(handler);
|
||||
streamHandlers.put(channel, handler);
|
||||
result.success(name);
|
||||
} catch (Exception e) {
|
||||
result.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void useEmulator(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String host,
|
||||
@NonNull Long port,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
try {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
firebaseAuth.useEmulator(host, port.intValue());
|
||||
result.success();
|
||||
} catch (Exception e) {
|
||||
result.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyActionCode(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String code,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
firebaseAuth
|
||||
.applyActionCode(code)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkActionCode(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String code,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalActionCodeInfo>
|
||||
result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
firebaseAuth
|
||||
.checkActionCode(code)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
ActionCodeResult actionCodeInfo = task.getResult();
|
||||
result.success(PigeonParser.parseActionCodeResult(actionCodeInfo));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void confirmPasswordReset(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String code,
|
||||
@NonNull String newPassword,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
|
||||
firebaseAuth
|
||||
.confirmPasswordReset(code, newPassword)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createUserWithEmailAndPassword(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String email,
|
||||
@NonNull String password,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserCredential>
|
||||
result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
|
||||
firebaseAuth
|
||||
.createUserWithEmailAndPassword(email, password)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
AuthResult authResult = task.getResult();
|
||||
result.success(PigeonParser.parseAuthResult(authResult));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void signInAnonymously(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserCredential>
|
||||
result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
firebaseAuth
|
||||
.signInAnonymously()
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
AuthResult authResult = task.getResult();
|
||||
result.success(PigeonParser.parseAuthResult(authResult));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void signInWithCredential(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull Map<String, Object> input,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserCredential>
|
||||
result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
AuthCredential credential = PigeonParser.getCredential(input);
|
||||
|
||||
if (credential == null) {
|
||||
throw FlutterFirebaseAuthPluginException.invalidCredential();
|
||||
}
|
||||
firebaseAuth
|
||||
.signInWithCredential(credential)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
AuthResult authResult = task.getResult();
|
||||
result.success(PigeonParser.parseAuthResult(authResult));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void signInWithCustomToken(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String token,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserCredential>
|
||||
result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
|
||||
firebaseAuth
|
||||
.signInWithCustomToken(token)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
AuthResult authResult = task.getResult();
|
||||
result.success(PigeonParser.parseAuthResult(authResult));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void signInWithEmailAndPassword(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String email,
|
||||
@NonNull String password,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserCredential>
|
||||
result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
firebaseAuth
|
||||
.signInWithEmailAndPassword(email, password)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success(PigeonParser.parseAuthResult(task.getResult()));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void signInWithEmailLink(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String email,
|
||||
@NonNull String emailLink,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserCredential>
|
||||
result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
firebaseAuth
|
||||
.signInWithEmailLink(email, emailLink)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
AuthResult authResult = task.getResult();
|
||||
result.success(PigeonParser.parseAuthResult(authResult));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void signInWithProvider(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.InternalSignInProvider signInProvider,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserCredential>
|
||||
result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
|
||||
OAuthProvider.Builder provider =
|
||||
OAuthProvider.newBuilder(signInProvider.getProviderId(), firebaseAuth);
|
||||
if (signInProvider.getScopes() != null) {
|
||||
provider.setScopes(signInProvider.getScopes());
|
||||
}
|
||||
if (signInProvider.getCustomParameters() != null) {
|
||||
provider.addCustomParameters(signInProvider.getCustomParameters());
|
||||
}
|
||||
|
||||
firebaseAuth
|
||||
.startActivityForSignInWithProvider(getActivity(), provider.build())
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
AuthResult authResult = task.getResult();
|
||||
result.success(PigeonParser.parseAuthResult(authResult));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void signOut(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
try {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
if (firebaseAuth.getCurrentUser() != null) {
|
||||
final Map<String, MultiFactor> appMultiFactorUser =
|
||||
multiFactorUserMap.get(app.getAppName());
|
||||
if (appMultiFactorUser != null) {
|
||||
appMultiFactorUser.remove(firebaseAuth.getCurrentUser().getUid());
|
||||
}
|
||||
}
|
||||
firebaseAuth.signOut();
|
||||
result.success();
|
||||
} catch (Exception e) {
|
||||
result.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchSignInMethodsForEmail(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String email,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.Result<List<String>> result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
|
||||
firebaseAuth
|
||||
.fetchSignInMethodsForEmail(email)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
SignInMethodQueryResult signInMethodQueryResult = task.getResult();
|
||||
result.success(signInMethodQueryResult.getSignInMethods());
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPasswordResetEmail(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String email,
|
||||
@Nullable GeneratedAndroidFirebaseAuth.InternalActionCodeSettings actionCodeSettings,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
|
||||
if (actionCodeSettings == null) {
|
||||
firebaseAuth
|
||||
.sendPasswordResetEmail(email)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
firebaseAuth
|
||||
.sendPasswordResetEmail(email, PigeonParser.getActionCodeSettings(actionCodeSettings))
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSignInLinkToEmail(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String email,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.InternalActionCodeSettings actionCodeSettings,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
|
||||
firebaseAuth
|
||||
.sendSignInLinkToEmail(email, PigeonParser.getActionCodeSettings(actionCodeSettings))
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLanguageCode(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@Nullable String languageCode,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.Result<String> result) {
|
||||
try {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
|
||||
if (languageCode == null) {
|
||||
firebaseAuth.useAppLanguage();
|
||||
} else {
|
||||
firebaseAuth.setLanguageCode(languageCode);
|
||||
}
|
||||
|
||||
result.success(firebaseAuth.getLanguageCode());
|
||||
} catch (Exception e) {
|
||||
result.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSettings(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.InternalFirebaseAuthSettings settings,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
try {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
|
||||
firebaseAuth
|
||||
.getFirebaseAuthSettings()
|
||||
.setAppVerificationDisabledForTesting(settings.getAppVerificationDisabledForTesting());
|
||||
|
||||
if (settings.getForceRecaptchaFlow() != null) {
|
||||
firebaseAuth
|
||||
.getFirebaseAuthSettings()
|
||||
.forceRecaptchaFlowForTesting(settings.getForceRecaptchaFlow());
|
||||
}
|
||||
|
||||
if (settings.getPhoneNumber() != null && settings.getSmsCode() != null) {
|
||||
firebaseAuth
|
||||
.getFirebaseAuthSettings()
|
||||
.setAutoRetrievedSmsCodeForPhoneNumber(
|
||||
settings.getPhoneNumber(), settings.getSmsCode());
|
||||
}
|
||||
|
||||
result.success();
|
||||
} catch (Exception e) {
|
||||
result.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verifyPasswordResetCode(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String code,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.Result<String> result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
|
||||
firebaseAuth
|
||||
.verifyPasswordResetCode(code)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success(task.getResult());
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verifyPhoneNumber(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.InternalVerifyPhoneNumberRequest request,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.Result<String> result) {
|
||||
try {
|
||||
String eventChannelName = METHOD_CHANNEL_NAME + "/phone/" + UUID.randomUUID().toString();
|
||||
EventChannel channel = new EventChannel(messenger, eventChannelName);
|
||||
|
||||
MultiFactorSession multiFactorSession = null;
|
||||
|
||||
if (request.getMultiFactorSessionId() != null) {
|
||||
multiFactorSession =
|
||||
FlutterFirebaseMultiFactor.multiFactorSessionMap.get(request.getMultiFactorSessionId());
|
||||
}
|
||||
|
||||
final String multiFactorInfoId = request.getMultiFactorInfoId();
|
||||
PhoneMultiFactorInfo multiFactorInfo = null;
|
||||
|
||||
if (multiFactorInfoId != null) {
|
||||
for (String resolverId : FlutterFirebaseMultiFactor.multiFactorResolverMap.keySet()) {
|
||||
for (MultiFactorInfo info :
|
||||
FlutterFirebaseMultiFactor.multiFactorResolverMap.get(resolverId).getHints()) {
|
||||
if (info.getUid().equals(multiFactorInfoId) && info instanceof PhoneMultiFactorInfo) {
|
||||
multiFactorInfo = (PhoneMultiFactorInfo) info;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PhoneNumberVerificationStreamHandler handler =
|
||||
new PhoneNumberVerificationStreamHandler(
|
||||
getActivity(),
|
||||
app,
|
||||
request,
|
||||
multiFactorSession,
|
||||
multiFactorInfo,
|
||||
credential -> {
|
||||
int hashCode = credential.hashCode();
|
||||
authCredentials.put(hashCode, credential);
|
||||
});
|
||||
|
||||
channel.setStreamHandler(handler);
|
||||
streamHandlers.put(channel, handler);
|
||||
|
||||
result.success(eventChannelName);
|
||||
} catch (Exception e) {
|
||||
result.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revokeTokenWithAuthorizationCode(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String authorizationCode,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
// Should never get here as we throw Exception on Dart side.
|
||||
result.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revokeAccessToken(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String accessToken,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
|
||||
firebaseAuth
|
||||
.revokeAccessToken(accessToken)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeRecaptchaConfig(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
FirebaseAuth firebaseAuth = getAuthFromPigeon(app);
|
||||
firebaseAuth
|
||||
.initializeRecaptchaConfig()
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task<Map<String, Object>> getPluginConstantsForFirebaseApp(FirebaseApp firebaseApp) {
|
||||
TaskCompletionSource<Map<String, Object>> taskCompletionSource = new TaskCompletionSource<>();
|
||||
|
||||
cachedThreadPool.execute(
|
||||
() -> {
|
||||
try {
|
||||
Map<String, Object> constants = new HashMap<>();
|
||||
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance(firebaseApp);
|
||||
FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
|
||||
String languageCode = firebaseAuth.getLanguageCode();
|
||||
|
||||
GeneratedAndroidFirebaseAuth.InternalUserDetails user =
|
||||
firebaseUser == null ? null : PigeonParser.parseFirebaseUser(firebaseUser);
|
||||
|
||||
if (languageCode != null) {
|
||||
constants.put("APP_LANGUAGE_CODE", languageCode);
|
||||
}
|
||||
|
||||
if (user != null) {
|
||||
constants.put("APP_CURRENT_USER", PigeonParser.manuallyToList(user));
|
||||
}
|
||||
|
||||
taskCompletionSource.setResult(constants);
|
||||
} catch (Exception e) {
|
||||
taskCompletionSource.setException(e);
|
||||
}
|
||||
});
|
||||
|
||||
return taskCompletionSource.getTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Task<Void> didReinitializeFirebaseCore() {
|
||||
TaskCompletionSource<Void> taskCompletionSource = new TaskCompletionSource<>();
|
||||
|
||||
cachedThreadPool.execute(
|
||||
() -> {
|
||||
try {
|
||||
removeEventListeners();
|
||||
authCredentials.clear();
|
||||
taskCompletionSource.setResult(null);
|
||||
} catch (Exception e) {
|
||||
taskCompletionSource.setException(e);
|
||||
}
|
||||
});
|
||||
|
||||
return taskCompletionSource.getTask();
|
||||
}
|
||||
|
||||
private void removeEventListeners() {
|
||||
for (EventChannel eventChannel : streamHandlers.keySet()) {
|
||||
StreamHandler streamHandler = streamHandlers.get(eventChannel);
|
||||
if (streamHandler != null) {
|
||||
streamHandler.onCancel(null);
|
||||
}
|
||||
eventChannel.setStreamHandler(null);
|
||||
}
|
||||
streamHandlers.clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright 2022, the Chromium project authors. Please see the AUTHORS file
|
||||
* for details. All rights reserved. Use of this source code is governed by a
|
||||
* BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package io.flutter.plugins.firebase.auth;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.firebase.FirebaseApiNotAvailableException;
|
||||
import com.google.firebase.FirebaseNetworkException;
|
||||
import com.google.firebase.FirebaseTooManyRequestsException;
|
||||
import com.google.firebase.auth.AuthCredential;
|
||||
import com.google.firebase.auth.FirebaseAuthException;
|
||||
import com.google.firebase.auth.FirebaseAuthMultiFactorException;
|
||||
import com.google.firebase.auth.FirebaseAuthUserCollisionException;
|
||||
import com.google.firebase.auth.FirebaseAuthWeakPasswordException;
|
||||
import com.google.firebase.auth.MultiFactorInfo;
|
||||
import com.google.firebase.auth.MultiFactorResolver;
|
||||
import com.google.firebase.auth.MultiFactorSession;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class FlutterFirebaseAuthPluginException {
|
||||
|
||||
static GeneratedAndroidFirebaseAuth.FlutterError parserExceptionToFlutter(
|
||||
@Nullable Exception nativeException) {
|
||||
if (nativeException == null) {
|
||||
return new GeneratedAndroidFirebaseAuth.FlutterError("UNKNOWN", null, null);
|
||||
}
|
||||
String code = "UNKNOWN";
|
||||
|
||||
String message = nativeException.getMessage();
|
||||
Map<String, Object> additionalData = new HashMap<>();
|
||||
|
||||
if (nativeException instanceof FirebaseAuthMultiFactorException) {
|
||||
final FirebaseAuthMultiFactorException multiFactorException =
|
||||
(FirebaseAuthMultiFactorException) nativeException;
|
||||
Map<String, Object> output = new HashMap<>();
|
||||
|
||||
MultiFactorResolver multiFactorResolver = multiFactorException.getResolver();
|
||||
final List<MultiFactorInfo> hints = multiFactorResolver.getHints();
|
||||
|
||||
final MultiFactorSession session = multiFactorResolver.getSession();
|
||||
final String sessionId = UUID.randomUUID().toString();
|
||||
FlutterFirebaseMultiFactor.multiFactorSessionMap.put(sessionId, session);
|
||||
|
||||
final String resolverId = UUID.randomUUID().toString();
|
||||
FlutterFirebaseMultiFactor.multiFactorResolverMap.put(resolverId, multiFactorResolver);
|
||||
|
||||
final List<List<Object>> pigeonHints = PigeonParser.multiFactorInfoToMap(hints);
|
||||
|
||||
output.put(
|
||||
Constants.APP_NAME,
|
||||
multiFactorException.getResolver().getFirebaseAuth().getApp().getName());
|
||||
|
||||
output.put(Constants.MULTI_FACTOR_HINTS, pigeonHints);
|
||||
|
||||
output.put(Constants.MULTI_FACTOR_SESSION_ID, sessionId);
|
||||
output.put(Constants.MULTI_FACTOR_RESOLVER_ID, resolverId);
|
||||
|
||||
return new GeneratedAndroidFirebaseAuth.FlutterError(
|
||||
multiFactorException.getErrorCode(), multiFactorException.getLocalizedMessage(), output);
|
||||
}
|
||||
|
||||
if (nativeException instanceof FirebaseNetworkException
|
||||
|| (nativeException.getCause() != null
|
||||
&& nativeException.getCause() instanceof FirebaseNetworkException)) {
|
||||
return new GeneratedAndroidFirebaseAuth.FlutterError(
|
||||
"network-request-failed",
|
||||
"A network error (such as timeout, interrupted connection or unreachable host) has"
|
||||
+ " occurred.",
|
||||
null);
|
||||
}
|
||||
|
||||
if (nativeException instanceof FirebaseApiNotAvailableException
|
||||
|| (nativeException.getCause() != null
|
||||
&& nativeException.getCause() instanceof FirebaseApiNotAvailableException)) {
|
||||
return new GeneratedAndroidFirebaseAuth.FlutterError(
|
||||
"api-not-available", "The requested API is not available.", null);
|
||||
}
|
||||
|
||||
if (nativeException instanceof FirebaseTooManyRequestsException
|
||||
|| (nativeException.getCause() != null
|
||||
&& nativeException.getCause() instanceof FirebaseTooManyRequestsException)) {
|
||||
return new GeneratedAndroidFirebaseAuth.FlutterError(
|
||||
"too-many-requests",
|
||||
"We have blocked all requests from this device due to unusual activity. Try again later.",
|
||||
null);
|
||||
}
|
||||
|
||||
// Manual message overrides to match other platforms.
|
||||
if (nativeException.getMessage() != null
|
||||
&& nativeException
|
||||
.getMessage()
|
||||
.startsWith("Cannot create PhoneAuthCredential without either verificationProof")) {
|
||||
return new GeneratedAndroidFirebaseAuth.FlutterError(
|
||||
"invalid-verification-code",
|
||||
"The verification ID used to create the phone auth credential is invalid.",
|
||||
null);
|
||||
}
|
||||
|
||||
if (message != null
|
||||
&& message.contains("User has already been linked to the given provider.")) {
|
||||
return FlutterFirebaseAuthPluginException.alreadyLinkedProvider();
|
||||
}
|
||||
|
||||
if (nativeException instanceof FirebaseAuthException) {
|
||||
code = ((FirebaseAuthException) nativeException).getErrorCode();
|
||||
}
|
||||
|
||||
if (nativeException instanceof FirebaseAuthWeakPasswordException) {
|
||||
message = ((FirebaseAuthWeakPasswordException) nativeException).getReason();
|
||||
}
|
||||
|
||||
if (nativeException instanceof FirebaseAuthUserCollisionException) {
|
||||
String email = ((FirebaseAuthUserCollisionException) nativeException).getEmail();
|
||||
|
||||
if (email != null) {
|
||||
additionalData.put("email", email);
|
||||
}
|
||||
|
||||
AuthCredential authCredential =
|
||||
((FirebaseAuthUserCollisionException) nativeException).getUpdatedCredential();
|
||||
|
||||
if (authCredential != null) {
|
||||
additionalData.put("authCredential", PigeonParser.parseAuthCredential(authCredential));
|
||||
}
|
||||
}
|
||||
|
||||
return new GeneratedAndroidFirebaseAuth.FlutterError(code, message, additionalData);
|
||||
}
|
||||
|
||||
static GeneratedAndroidFirebaseAuth.FlutterError noUser() {
|
||||
return new GeneratedAndroidFirebaseAuth.FlutterError(
|
||||
"NO_CURRENT_USER", "No user currently signed in.", null);
|
||||
}
|
||||
|
||||
static GeneratedAndroidFirebaseAuth.FlutterError invalidCredential() {
|
||||
return new GeneratedAndroidFirebaseAuth.FlutterError(
|
||||
"INVALID_CREDENTIAL",
|
||||
"The supplied auth credential is malformed, has expired or is not currently supported.",
|
||||
null);
|
||||
}
|
||||
|
||||
static GeneratedAndroidFirebaseAuth.FlutterError noSuchProvider() {
|
||||
return new GeneratedAndroidFirebaseAuth.FlutterError(
|
||||
"NO_SUCH_PROVIDER", "User was not linked to an account with the given provider.", null);
|
||||
}
|
||||
|
||||
static GeneratedAndroidFirebaseAuth.FlutterError alreadyLinkedProvider() {
|
||||
return new GeneratedAndroidFirebaseAuth.FlutterError(
|
||||
"PROVIDER_ALREADY_LINKED", "User has already been linked to the given provider.", null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2019 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package io.flutter.plugins.firebase.auth;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
import com.google.firebase.components.Component;
|
||||
import com.google.firebase.components.ComponentRegistrar;
|
||||
import com.google.firebase.platforminfo.LibraryVersionComponent;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Keep
|
||||
public class FlutterFirebaseAuthRegistrar implements ComponentRegistrar {
|
||||
@Override
|
||||
public List<Component<?>> getComponents() {
|
||||
return Collections.<Component<?>>singletonList(
|
||||
LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,548 @@
|
|||
/*
|
||||
* Copyright 2023, the Chromium project authors. Please see the AUTHORS file
|
||||
* for details. All rights reserved. Use of this source code is governed by a
|
||||
* BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package io.flutter.plugins.firebase.auth;
|
||||
|
||||
import static io.flutter.plugins.firebase.core.FlutterFirebasePlugin.cachedThreadPool;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.gms.tasks.Tasks;
|
||||
import com.google.firebase.FirebaseApp;
|
||||
import com.google.firebase.auth.AuthCredential;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.auth.FirebaseUser;
|
||||
import com.google.firebase.auth.GetTokenResult;
|
||||
import com.google.firebase.auth.OAuthProvider;
|
||||
import com.google.firebase.auth.PhoneAuthCredential;
|
||||
import com.google.firebase.auth.UserProfileChangeRequest;
|
||||
import java.util.Map;
|
||||
|
||||
public class FlutterFirebaseAuthUser
|
||||
implements GeneratedAndroidFirebaseAuth.FirebaseAuthUserHostApi {
|
||||
|
||||
private Activity activity;
|
||||
|
||||
public void setActivity(Activity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
public static FirebaseUser getCurrentUserFromPigeon(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp pigeonApp) {
|
||||
FirebaseApp app = FirebaseApp.getInstance(pigeonApp.getAppName());
|
||||
FirebaseAuth auth = FirebaseAuth.getInstance(app);
|
||||
if (pigeonApp.getTenantId() != null) {
|
||||
auth.setTenantId(pigeonApp.getTenantId());
|
||||
}
|
||||
|
||||
return auth.getCurrentUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
FirebaseUser firebaseUser = getCurrentUserFromPigeon(app);
|
||||
|
||||
if (firebaseUser == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.noUser());
|
||||
return;
|
||||
}
|
||||
|
||||
firebaseUser
|
||||
.delete()
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getIdToken(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull Boolean forceRefresh,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalIdTokenResult>
|
||||
result) {
|
||||
cachedThreadPool.execute(
|
||||
() -> {
|
||||
FirebaseUser firebaseUser = getCurrentUserFromPigeon(app);
|
||||
|
||||
if (firebaseUser == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.noUser());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
GetTokenResult response = Tasks.await(firebaseUser.getIdToken(forceRefresh));
|
||||
result.success(PigeonParser.parseTokenResult(response));
|
||||
} catch (Exception exception) {
|
||||
result.error(FlutterFirebaseAuthPluginException.parserExceptionToFlutter(exception));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void linkWithCredential(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull Map<String, Object> input,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserCredential>
|
||||
result) {
|
||||
FirebaseUser firebaseUser = getCurrentUserFromPigeon(app);
|
||||
AuthCredential credential = PigeonParser.getCredential(input);
|
||||
|
||||
if (firebaseUser == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.noUser());
|
||||
return;
|
||||
}
|
||||
|
||||
if (credential == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.invalidCredential());
|
||||
return;
|
||||
}
|
||||
|
||||
firebaseUser
|
||||
.linkWithCredential(credential)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success(PigeonParser.parseAuthResult(task.getResult()));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void linkWithProvider(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.InternalSignInProvider signInProvider,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserCredential>
|
||||
result) {
|
||||
FirebaseUser firebaseUser = getCurrentUserFromPigeon(app);
|
||||
|
||||
OAuthProvider.Builder provider = OAuthProvider.newBuilder(signInProvider.getProviderId());
|
||||
if (signInProvider.getScopes() != null) {
|
||||
provider.setScopes(signInProvider.getScopes());
|
||||
}
|
||||
if (signInProvider.getCustomParameters() != null) {
|
||||
provider.addCustomParameters(signInProvider.getCustomParameters());
|
||||
}
|
||||
|
||||
firebaseUser
|
||||
.startActivityForLinkWithProvider(activity, provider.build())
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success(PigeonParser.parseAuthResult(task.getResult()));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reauthenticateWithCredential(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull Map<String, Object> input,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserCredential>
|
||||
result) {
|
||||
FirebaseUser firebaseUser = getCurrentUserFromPigeon(app);
|
||||
AuthCredential credential = PigeonParser.getCredential(input);
|
||||
|
||||
if (firebaseUser == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.noUser());
|
||||
return;
|
||||
}
|
||||
|
||||
if (credential == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.invalidCredential());
|
||||
return;
|
||||
}
|
||||
|
||||
firebaseUser
|
||||
.reauthenticateAndRetrieveData(credential)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success(PigeonParser.parseAuthResult(task.getResult()));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reauthenticateWithProvider(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.InternalSignInProvider signInProvider,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserCredential>
|
||||
result) {
|
||||
FirebaseUser firebaseUser = getCurrentUserFromPigeon(app);
|
||||
|
||||
OAuthProvider.Builder provider = OAuthProvider.newBuilder(signInProvider.getProviderId());
|
||||
if (signInProvider.getScopes() != null) {
|
||||
provider.setScopes(signInProvider.getScopes());
|
||||
}
|
||||
if (signInProvider.getCustomParameters() != null) {
|
||||
provider.addCustomParameters(signInProvider.getCustomParameters());
|
||||
}
|
||||
|
||||
firebaseUser
|
||||
.startActivityForReauthenticateWithProvider(activity, provider.build())
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success(PigeonParser.parseAuthResult(task.getResult()));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserDetails>
|
||||
result) {
|
||||
FirebaseUser firebaseUser = getCurrentUserFromPigeon(app);
|
||||
|
||||
if (firebaseUser == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.noUser());
|
||||
return;
|
||||
}
|
||||
|
||||
firebaseUser
|
||||
.reload()
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success(PigeonParser.parseFirebaseUser(firebaseUser));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendEmailVerification(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@Nullable GeneratedAndroidFirebaseAuth.InternalActionCodeSettings actionCodeSettings,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
FirebaseUser firebaseUser = getCurrentUserFromPigeon(app);
|
||||
|
||||
if (firebaseUser == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.noUser());
|
||||
return;
|
||||
}
|
||||
|
||||
if (actionCodeSettings == null) {
|
||||
firebaseUser
|
||||
.sendEmailVerification()
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
firebaseUser
|
||||
.sendEmailVerification(PigeonParser.getActionCodeSettings(actionCodeSettings))
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unlink(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String providerId,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserCredential>
|
||||
result) {
|
||||
FirebaseUser firebaseUser = getCurrentUserFromPigeon(app);
|
||||
|
||||
if (firebaseUser == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.noUser());
|
||||
return;
|
||||
}
|
||||
|
||||
firebaseUser
|
||||
.unlink(providerId)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success(PigeonParser.parseAuthResult(task.getResult()));
|
||||
} else {
|
||||
Exception exception = task.getException();
|
||||
if (exception
|
||||
.getMessage()
|
||||
.contains("User was not linked to an account with the given provider.")) {
|
||||
result.error(FlutterFirebaseAuthPluginException.noSuchProvider());
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(exception));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEmail(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String newEmail,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserDetails>
|
||||
result) {
|
||||
FirebaseUser firebaseUser = getCurrentUserFromPigeon(app);
|
||||
|
||||
if (firebaseUser == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.noUser());
|
||||
return;
|
||||
}
|
||||
|
||||
firebaseUser
|
||||
.updateEmail(newEmail)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
firebaseUser
|
||||
.reload()
|
||||
.addOnCompleteListener(
|
||||
reloadTask -> {
|
||||
if (reloadTask.isSuccessful()) {
|
||||
result.success(PigeonParser.parseFirebaseUser(firebaseUser));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
reloadTask.getException()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePassword(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String newPassword,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserDetails>
|
||||
result) {
|
||||
FirebaseUser firebaseUser = getCurrentUserFromPigeon(app);
|
||||
|
||||
if (firebaseUser == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.noUser());
|
||||
return;
|
||||
}
|
||||
|
||||
firebaseUser
|
||||
.updatePassword(newPassword)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
firebaseUser
|
||||
.reload()
|
||||
.addOnCompleteListener(
|
||||
reloadTask -> {
|
||||
if (reloadTask.isSuccessful()) {
|
||||
result.success(PigeonParser.parseFirebaseUser(firebaseUser));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
reloadTask.getException()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePhoneNumber(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull Map<String, Object> input,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserDetails>
|
||||
result) {
|
||||
FirebaseUser firebaseUser = getCurrentUserFromPigeon(app);
|
||||
|
||||
if (firebaseUser == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.noUser());
|
||||
return;
|
||||
}
|
||||
|
||||
PhoneAuthCredential phoneAuthCredential =
|
||||
(PhoneAuthCredential) PigeonParser.getCredential(input);
|
||||
|
||||
if (phoneAuthCredential == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.invalidCredential());
|
||||
return;
|
||||
}
|
||||
|
||||
firebaseUser
|
||||
.updatePhoneNumber(phoneAuthCredential)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
firebaseUser
|
||||
.reload()
|
||||
.addOnCompleteListener(
|
||||
reloadTask -> {
|
||||
if (reloadTask.isSuccessful()) {
|
||||
result.success(PigeonParser.parseFirebaseUser(firebaseUser));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
reloadTask.getException()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateProfile(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.InternalUserProfile profile,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserDetails>
|
||||
result) {
|
||||
FirebaseUser firebaseUser = getCurrentUserFromPigeon(app);
|
||||
|
||||
if (firebaseUser == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.noUser());
|
||||
return;
|
||||
}
|
||||
|
||||
UserProfileChangeRequest.Builder builder = new UserProfileChangeRequest.Builder();
|
||||
|
||||
if (profile.getDisplayNameChanged()) {
|
||||
builder.setDisplayName(profile.getDisplayName());
|
||||
}
|
||||
|
||||
if (profile.getPhotoUrlChanged()) {
|
||||
if (profile.getPhotoUrl() != null) {
|
||||
builder.setPhotoUri(Uri.parse(profile.getPhotoUrl()));
|
||||
} else {
|
||||
builder.setPhotoUri(null);
|
||||
}
|
||||
}
|
||||
|
||||
firebaseUser
|
||||
.updateProfile(builder.build())
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
firebaseUser
|
||||
.reload()
|
||||
.addOnCompleteListener(
|
||||
reloadTask -> {
|
||||
if (reloadTask.isSuccessful()) {
|
||||
result.success(PigeonParser.parseFirebaseUser(firebaseUser));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
reloadTask.getException()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verifyBeforeUpdateEmail(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String newEmail,
|
||||
@Nullable GeneratedAndroidFirebaseAuth.InternalActionCodeSettings actionCodeSettings,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
FirebaseUser firebaseUser = getCurrentUserFromPigeon(app);
|
||||
|
||||
if (firebaseUser == null) {
|
||||
result.error(FlutterFirebaseAuthPluginException.noUser());
|
||||
return;
|
||||
}
|
||||
|
||||
if (actionCodeSettings == null) {
|
||||
firebaseUser
|
||||
.verifyBeforeUpdateEmail(newEmail)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
firebaseUser
|
||||
.verifyBeforeUpdateEmail(newEmail, PigeonParser.getActionCodeSettings(actionCodeSettings))
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* Copyright 2023, the Chromium project authors. Please see the AUTHORS file
|
||||
* for details. All rights reserved. Use of this source code is governed by a
|
||||
* BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package io.flutter.plugins.firebase.auth;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.firebase.auth.AuthResult;
|
||||
import com.google.firebase.auth.FirebaseUser;
|
||||
import com.google.firebase.auth.MultiFactor;
|
||||
import com.google.firebase.auth.MultiFactorAssertion;
|
||||
import com.google.firebase.auth.MultiFactorInfo;
|
||||
import com.google.firebase.auth.MultiFactorResolver;
|
||||
import com.google.firebase.auth.MultiFactorSession;
|
||||
import com.google.firebase.auth.PhoneAuthCredential;
|
||||
import com.google.firebase.auth.PhoneAuthProvider;
|
||||
import com.google.firebase.auth.PhoneMultiFactorGenerator;
|
||||
import com.google.firebase.internal.api.FirebaseNoSignedInUserException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class FlutterFirebaseMultiFactor
|
||||
implements GeneratedAndroidFirebaseAuth.MultiFactorUserHostApi,
|
||||
GeneratedAndroidFirebaseAuth.MultiFactoResolverHostApi {
|
||||
|
||||
// Map an app id to a map of user id to a MultiFactorUser object.
|
||||
static final Map<String, Map<String, MultiFactor>> multiFactorUserMap = new HashMap<>();
|
||||
|
||||
// Map an id to a MultiFactorSession object.
|
||||
static final Map<String, MultiFactorSession> multiFactorSessionMap = new HashMap<>();
|
||||
|
||||
// Map an id to a MultiFactorResolver object.
|
||||
static final Map<String, MultiFactorResolver> multiFactorResolverMap = new HashMap<>();
|
||||
|
||||
static final Map<String, MultiFactorAssertion> multiFactorAssertionMap = new HashMap<>();
|
||||
|
||||
MultiFactor getAppMultiFactor(@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app)
|
||||
throws FirebaseNoSignedInUserException {
|
||||
final FirebaseUser currentUser = FlutterFirebaseAuthUser.getCurrentUserFromPigeon(app);
|
||||
if (currentUser == null) {
|
||||
throw new FirebaseNoSignedInUserException("No user is signed in");
|
||||
}
|
||||
if (multiFactorUserMap.get(app.getAppName()) == null) {
|
||||
multiFactorUserMap.put(app.getAppName(), new HashMap<>());
|
||||
}
|
||||
|
||||
final Map<String, MultiFactor> appMultiFactorUser = multiFactorUserMap.get(app.getAppName());
|
||||
if (appMultiFactorUser.get(currentUser.getUid()) == null) {
|
||||
appMultiFactorUser.put(currentUser.getUid(), currentUser.getMultiFactor());
|
||||
}
|
||||
|
||||
return appMultiFactorUser.get(currentUser.getUid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enrollPhone(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.InternalPhoneMultiFactorAssertion assertion,
|
||||
@Nullable String displayName,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
final MultiFactor multiFactor;
|
||||
try {
|
||||
multiFactor = getAppMultiFactor(app);
|
||||
} catch (FirebaseNoSignedInUserException e) {
|
||||
result.error(e);
|
||||
return;
|
||||
}
|
||||
|
||||
PhoneAuthCredential credential =
|
||||
PhoneAuthProvider.getCredential(
|
||||
assertion.getVerificationId(), assertion.getVerificationCode());
|
||||
|
||||
MultiFactorAssertion multiFactorAssertion = PhoneMultiFactorGenerator.getAssertion(credential);
|
||||
|
||||
multiFactor
|
||||
.enroll(multiFactorAssertion, displayName)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enrollTotp(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String assertionId,
|
||||
@Nullable String displayName,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
final MultiFactor multiFactor;
|
||||
try {
|
||||
multiFactor = getAppMultiFactor(app);
|
||||
} catch (FirebaseNoSignedInUserException e) {
|
||||
result.error(e);
|
||||
return;
|
||||
}
|
||||
|
||||
final MultiFactorAssertion multiFactorAssertion = multiFactorAssertionMap.get(assertionId);
|
||||
|
||||
assert multiFactorAssertion != null;
|
||||
multiFactor
|
||||
.enroll(multiFactorAssertion, displayName)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getSession(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<
|
||||
GeneratedAndroidFirebaseAuth.InternalMultiFactorSession>
|
||||
result) {
|
||||
final MultiFactor multiFactor;
|
||||
try {
|
||||
multiFactor = getAppMultiFactor(app);
|
||||
} catch (FirebaseNoSignedInUserException e) {
|
||||
result.error(e);
|
||||
return;
|
||||
}
|
||||
|
||||
multiFactor
|
||||
.getSession()
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
final MultiFactorSession sessionResult = task.getResult();
|
||||
final String id = UUID.randomUUID().toString();
|
||||
multiFactorSessionMap.put(id, sessionResult);
|
||||
result.success(
|
||||
new GeneratedAndroidFirebaseAuth.InternalMultiFactorSession.Builder()
|
||||
.setId(id)
|
||||
.build());
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unenroll(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull String factorUid,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
final MultiFactor multiFactor;
|
||||
try {
|
||||
multiFactor = getAppMultiFactor(app);
|
||||
} catch (FirebaseNoSignedInUserException e) {
|
||||
result.error(FlutterFirebaseAuthPluginException.parserExceptionToFlutter(e));
|
||||
return;
|
||||
}
|
||||
|
||||
multiFactor
|
||||
.unenroll(factorUid)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
result.success();
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getEnrolledFactors(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<
|
||||
List<GeneratedAndroidFirebaseAuth.InternalMultiFactorInfo>>
|
||||
result) {
|
||||
final MultiFactor multiFactor;
|
||||
try {
|
||||
multiFactor = getAppMultiFactor(app);
|
||||
} catch (FirebaseNoSignedInUserException e) {
|
||||
result.error(e);
|
||||
return;
|
||||
}
|
||||
|
||||
final List<MultiFactorInfo> factors = multiFactor.getEnrolledFactors();
|
||||
|
||||
final List<GeneratedAndroidFirebaseAuth.InternalMultiFactorInfo> resultFactors =
|
||||
PigeonParser.multiFactorInfoToPigeon(factors);
|
||||
|
||||
result.success(resultFactors);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolveSignIn(
|
||||
@NonNull String resolverId,
|
||||
@Nullable GeneratedAndroidFirebaseAuth.InternalPhoneMultiFactorAssertion assertion,
|
||||
@Nullable String totpAssertionId,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalUserCredential>
|
||||
result) {
|
||||
final MultiFactorResolver resolver = multiFactorResolverMap.get(resolverId);
|
||||
|
||||
if (resolver == null) {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
new Exception("Resolver not found")));
|
||||
return;
|
||||
}
|
||||
|
||||
MultiFactorAssertion multiFactorAssertion;
|
||||
|
||||
if (assertion != null) {
|
||||
PhoneAuthCredential credential =
|
||||
PhoneAuthProvider.getCredential(
|
||||
assertion.getVerificationId(), assertion.getVerificationCode());
|
||||
multiFactorAssertion = PhoneMultiFactorGenerator.getAssertion(credential);
|
||||
} else {
|
||||
multiFactorAssertion = multiFactorAssertionMap.get(totpAssertionId);
|
||||
}
|
||||
|
||||
resolver
|
||||
.resolveSignIn(multiFactorAssertion)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
final AuthResult authResult = task.getResult();
|
||||
result.success(PigeonParser.parseAuthResult(authResult));
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright 2023, the Chromium project authors. Please see the AUTHORS file
|
||||
* for details. All rights reserved. Use of this source code is governed by a
|
||||
* BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package io.flutter.plugins.firebase.auth;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import com.google.firebase.auth.MultiFactorSession;
|
||||
import com.google.firebase.auth.TotpMultiFactorAssertion;
|
||||
import com.google.firebase.auth.TotpMultiFactorGenerator;
|
||||
import com.google.firebase.auth.TotpSecret;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class FlutterFirebaseTotpMultiFactor
|
||||
implements GeneratedAndroidFirebaseAuth.MultiFactorTotpHostApi {
|
||||
|
||||
// Map an app id to a map of user id to a TotpSecret object.
|
||||
static final Map<String, TotpSecret> multiFactorSecret = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void generateSecret(
|
||||
@NonNull String sessionId,
|
||||
@NonNull
|
||||
GeneratedAndroidFirebaseAuth.Result<GeneratedAndroidFirebaseAuth.InternalTotpSecret>
|
||||
result) {
|
||||
MultiFactorSession multiFactorSession =
|
||||
FlutterFirebaseMultiFactor.multiFactorSessionMap.get(sessionId);
|
||||
|
||||
assert multiFactorSession != null;
|
||||
TotpMultiFactorGenerator.generateSecret(multiFactorSession)
|
||||
.addOnCompleteListener(
|
||||
task -> {
|
||||
if (task.isSuccessful()) {
|
||||
TotpSecret secret = task.getResult();
|
||||
multiFactorSecret.put(secret.getSharedSecretKey(), secret);
|
||||
result.success(
|
||||
new GeneratedAndroidFirebaseAuth.InternalTotpSecret.Builder()
|
||||
.setCodeIntervalSeconds((long) secret.getCodeIntervalSeconds())
|
||||
.setCodeLength((long) secret.getCodeLength())
|
||||
.setSecretKey(secret.getSharedSecretKey())
|
||||
.setHashingAlgorithm(secret.getHashAlgorithm())
|
||||
.setEnrollmentCompletionDeadline(secret.getEnrollmentCompletionDeadline())
|
||||
.build());
|
||||
} else {
|
||||
result.error(
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(
|
||||
task.getException()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAssertionForEnrollment(
|
||||
@NonNull String secretKey,
|
||||
@NonNull String oneTimePassword,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.Result<String> result) {
|
||||
final TotpSecret secret = multiFactorSecret.get(secretKey);
|
||||
|
||||
assert secret != null;
|
||||
TotpMultiFactorAssertion assertion =
|
||||
TotpMultiFactorGenerator.getAssertionForEnrollment(secret, oneTimePassword);
|
||||
String assertionId = UUID.randomUUID().toString();
|
||||
FlutterFirebaseMultiFactor.multiFactorAssertionMap.put(assertionId, assertion);
|
||||
result.success(assertionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAssertionForSignIn(
|
||||
@NonNull String enrollmentId,
|
||||
@NonNull String oneTimePassword,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.Result<String> result) {
|
||||
TotpMultiFactorAssertion assertion =
|
||||
TotpMultiFactorGenerator.getAssertionForSignIn(enrollmentId, oneTimePassword);
|
||||
String assertionId = UUID.randomUUID().toString();
|
||||
FlutterFirebaseMultiFactor.multiFactorAssertionMap.put(assertionId, assertion);
|
||||
result.success(assertionId);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright 2023, the Chromium project authors. Please see the AUTHORS file
|
||||
* for details. All rights reserved. Use of this source code is governed by a
|
||||
* BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package io.flutter.plugins.firebase.auth;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.firebase.auth.TotpSecret;
|
||||
|
||||
public class FlutterFirebaseTotpSecret
|
||||
implements GeneratedAndroidFirebaseAuth.MultiFactorTotpSecretHostApi {
|
||||
|
||||
@Override
|
||||
public void generateQrCodeUrl(
|
||||
@NonNull String secretKey,
|
||||
@Nullable String accountName,
|
||||
@Nullable String issuer,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.Result<String> result) {
|
||||
final TotpSecret secret = FlutterFirebaseTotpMultiFactor.multiFactorSecret.get(secretKey);
|
||||
|
||||
assert secret != null;
|
||||
if (accountName == null || issuer == null) {
|
||||
result.success(secret.generateQrCodeUrl());
|
||||
return;
|
||||
}
|
||||
result.success(secret.generateQrCodeUrl(accountName, issuer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openInOtpApp(
|
||||
@NonNull String secretKey,
|
||||
@NonNull String qrCodeUrl,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.VoidResult result) {
|
||||
final TotpSecret secret = FlutterFirebaseTotpMultiFactor.multiFactorSecret.get(secretKey);
|
||||
assert secret != null;
|
||||
secret.openInOtpApp(qrCodeUrl);
|
||||
result.success();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 2022, the Chromium project authors. Please see the AUTHORS file
|
||||
* for details. All rights reserved. Use of this source code is governed by a
|
||||
* BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package io.flutter.plugins.firebase.auth;
|
||||
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.auth.FirebaseAuth.IdTokenListener;
|
||||
import com.google.firebase.auth.FirebaseUser;
|
||||
import io.flutter.plugin.common.EventChannel.EventSink;
|
||||
import io.flutter.plugin.common.EventChannel.StreamHandler;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class IdTokenChannelStreamHandler implements StreamHandler {
|
||||
|
||||
private final FirebaseAuth firebaseAuth;
|
||||
private IdTokenListener idTokenListener;
|
||||
|
||||
public IdTokenChannelStreamHandler(FirebaseAuth firebaseAuth) {
|
||||
this.firebaseAuth = firebaseAuth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListen(Object arguments, EventSink events) {
|
||||
Map<String, Object> event = new HashMap<>();
|
||||
event.put(Constants.APP_NAME, firebaseAuth.getApp().getName());
|
||||
|
||||
final AtomicBoolean initialAuthState = new AtomicBoolean(true);
|
||||
|
||||
idTokenListener =
|
||||
auth -> {
|
||||
if (initialAuthState.get()) {
|
||||
initialAuthState.set(false);
|
||||
return;
|
||||
}
|
||||
|
||||
FirebaseUser user = auth.getCurrentUser();
|
||||
|
||||
if (user == null) {
|
||||
event.put(Constants.USER, null);
|
||||
} else {
|
||||
event.put(
|
||||
Constants.USER, PigeonParser.manuallyToList(PigeonParser.parseFirebaseUser(user)));
|
||||
}
|
||||
|
||||
events.success(event);
|
||||
};
|
||||
|
||||
firebaseAuth.addIdTokenListener(idTokenListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(Object arguments) {
|
||||
if (idTokenListener != null) {
|
||||
firebaseAuth.removeIdTokenListener(idTokenListener);
|
||||
idTokenListener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright 2022, the Chromium project authors. Please see the AUTHORS file
|
||||
* for details. All rights reserved. Use of this source code is governed by a
|
||||
* BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package io.flutter.plugins.firebase.auth;
|
||||
|
||||
import android.app.Activity;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.firebase.FirebaseException;
|
||||
import com.google.firebase.auth.FirebaseAuth;
|
||||
import com.google.firebase.auth.MultiFactorSession;
|
||||
import com.google.firebase.auth.PhoneAuthCredential;
|
||||
import com.google.firebase.auth.PhoneAuthOptions;
|
||||
import com.google.firebase.auth.PhoneAuthProvider;
|
||||
import com.google.firebase.auth.PhoneAuthProvider.ForceResendingToken;
|
||||
import com.google.firebase.auth.PhoneMultiFactorInfo;
|
||||
import io.flutter.plugin.common.EventChannel.EventSink;
|
||||
import io.flutter.plugin.common.EventChannel.StreamHandler;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class PhoneNumberVerificationStreamHandler implements StreamHandler {
|
||||
|
||||
interface OnCredentialsListener {
|
||||
void onCredentialsReceived(PhoneAuthCredential credential);
|
||||
}
|
||||
|
||||
final AtomicReference<Activity> activityRef = new AtomicReference<>(null);
|
||||
final FirebaseAuth firebaseAuth;
|
||||
final String phoneNumber;
|
||||
final PhoneMultiFactorInfo multiFactorInfo;
|
||||
final int timeout;
|
||||
final OnCredentialsListener onCredentialsListener;
|
||||
|
||||
final MultiFactorSession multiFactorSession;
|
||||
|
||||
String autoRetrievedSmsCodeForTesting;
|
||||
Integer forceResendingToken;
|
||||
|
||||
private static final HashMap<Integer, ForceResendingToken> forceResendingTokens = new HashMap<>();
|
||||
|
||||
@Nullable private EventSink eventSink;
|
||||
|
||||
public PhoneNumberVerificationStreamHandler(
|
||||
Activity activity,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app,
|
||||
@NonNull GeneratedAndroidFirebaseAuth.InternalVerifyPhoneNumberRequest request,
|
||||
@Nullable MultiFactorSession multiFactorSession,
|
||||
@Nullable PhoneMultiFactorInfo multiFactorInfo,
|
||||
OnCredentialsListener onCredentialsListener) {
|
||||
this.activityRef.set(activity);
|
||||
|
||||
this.multiFactorSession = multiFactorSession;
|
||||
this.multiFactorInfo = multiFactorInfo;
|
||||
firebaseAuth = FlutterFirebaseAuthPlugin.getAuthFromPigeon(app);
|
||||
phoneNumber = request.getPhoneNumber();
|
||||
timeout = Math.toIntExact(request.getTimeout());
|
||||
|
||||
if (request.getAutoRetrievedSmsCodeForTesting() != null) {
|
||||
autoRetrievedSmsCodeForTesting = request.getAutoRetrievedSmsCodeForTesting();
|
||||
}
|
||||
|
||||
if (request.getForceResendingToken() != null) {
|
||||
forceResendingToken = Math.toIntExact(request.getForceResendingToken());
|
||||
}
|
||||
|
||||
this.onCredentialsListener = onCredentialsListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListen(Object arguments, EventSink events) {
|
||||
eventSink = events;
|
||||
|
||||
PhoneAuthProvider.OnVerificationStateChangedCallbacks callbacks =
|
||||
new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
|
||||
@Override
|
||||
public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCredential) {
|
||||
int phoneAuthCredentialHashCode = phoneAuthCredential.hashCode();
|
||||
onCredentialsListener.onCredentialsReceived(phoneAuthCredential);
|
||||
|
||||
Map<String, Object> event = new HashMap<>();
|
||||
event.put(Constants.TOKEN, phoneAuthCredentialHashCode);
|
||||
|
||||
if (phoneAuthCredential.getSmsCode() != null) {
|
||||
event.put(Constants.SMS_CODE, phoneAuthCredential.getSmsCode());
|
||||
}
|
||||
|
||||
event.put(Constants.NAME, "Auth#phoneVerificationCompleted");
|
||||
|
||||
if (eventSink != null) {
|
||||
eventSink.success(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVerificationFailed(@NonNull FirebaseException e) {
|
||||
Map<String, Object> event = new HashMap<>();
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
GeneratedAndroidFirebaseAuth.FlutterError flutterError =
|
||||
FlutterFirebaseAuthPluginException.parserExceptionToFlutter(e);
|
||||
error.put(
|
||||
"code",
|
||||
flutterError
|
||||
.code
|
||||
.replaceAll("ERROR_", "")
|
||||
.toLowerCase(Locale.ROOT)
|
||||
.replaceAll("_", "-"));
|
||||
error.put("message", flutterError.getMessage());
|
||||
error.put("details", flutterError.details);
|
||||
event.put("error", error);
|
||||
|
||||
event.put(Constants.NAME, "Auth#phoneVerificationFailed");
|
||||
|
||||
if (eventSink != null) {
|
||||
eventSink.success(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCodeSent(
|
||||
@NonNull String verificationId,
|
||||
@NonNull PhoneAuthProvider.ForceResendingToken token) {
|
||||
int forceResendingTokenHashCode = token.hashCode();
|
||||
forceResendingTokens.put(forceResendingTokenHashCode, token);
|
||||
|
||||
Map<String, Object> event = new HashMap<>();
|
||||
event.put(Constants.VERIFICATION_ID, verificationId);
|
||||
event.put(Constants.FORCE_RESENDING_TOKEN, forceResendingTokenHashCode);
|
||||
|
||||
event.put(Constants.NAME, "Auth#phoneCodeSent");
|
||||
|
||||
if (eventSink != null) {
|
||||
eventSink.success(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCodeAutoRetrievalTimeOut(@NonNull String verificationId) {
|
||||
Map<String, Object> event = new HashMap<>();
|
||||
event.put(Constants.VERIFICATION_ID, verificationId);
|
||||
|
||||
event.put(Constants.NAME, "Auth#phoneCodeAutoRetrievalTimeout");
|
||||
|
||||
if (eventSink != null) {
|
||||
eventSink.success(event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Allows the auto-retrieval flow to be tested.
|
||||
// See https://firebase.google.com/docs/auth/android/phone-auth#integration-testing
|
||||
if (autoRetrievedSmsCodeForTesting != null) {
|
||||
firebaseAuth
|
||||
.getFirebaseAuthSettings()
|
||||
.setAutoRetrievedSmsCodeForPhoneNumber(phoneNumber, autoRetrievedSmsCodeForTesting);
|
||||
}
|
||||
|
||||
PhoneAuthOptions.Builder phoneAuthOptionsBuilder = new PhoneAuthOptions.Builder(firebaseAuth);
|
||||
phoneAuthOptionsBuilder.setActivity(activityRef.get());
|
||||
phoneAuthOptionsBuilder.setCallbacks(callbacks);
|
||||
|
||||
if (phoneNumber != null) {
|
||||
phoneAuthOptionsBuilder.setPhoneNumber(phoneNumber);
|
||||
}
|
||||
if (multiFactorSession != null) {
|
||||
phoneAuthOptionsBuilder.setMultiFactorSession(multiFactorSession);
|
||||
}
|
||||
if (multiFactorInfo != null) {
|
||||
phoneAuthOptionsBuilder.setMultiFactorHint(multiFactorInfo);
|
||||
}
|
||||
phoneAuthOptionsBuilder.setTimeout((long) timeout, TimeUnit.MILLISECONDS);
|
||||
|
||||
if (forceResendingToken != null) {
|
||||
PhoneAuthProvider.ForceResendingToken forceResendingToken =
|
||||
forceResendingTokens.get(this.forceResendingToken);
|
||||
|
||||
if (forceResendingToken != null) {
|
||||
phoneAuthOptionsBuilder.setForceResendingToken(forceResendingToken);
|
||||
}
|
||||
}
|
||||
|
||||
PhoneAuthProvider.verifyPhoneNumber(phoneAuthOptionsBuilder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(Object arguments) {
|
||||
eventSink = null;
|
||||
|
||||
activityRef.set(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,382 @@
|
|||
/*
|
||||
* Copyright 2023, the Chromium project authors. Please see the AUTHORS file
|
||||
* for details. All rights reserved. Use of this source code is governed by a
|
||||
* BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package io.flutter.plugins.firebase.auth;
|
||||
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import com.google.firebase.auth.ActionCodeEmailInfo;
|
||||
import com.google.firebase.auth.ActionCodeInfo;
|
||||
import com.google.firebase.auth.ActionCodeResult;
|
||||
import com.google.firebase.auth.ActionCodeSettings;
|
||||
import com.google.firebase.auth.AdditionalUserInfo;
|
||||
import com.google.firebase.auth.AuthCredential;
|
||||
import com.google.firebase.auth.AuthResult;
|
||||
import com.google.firebase.auth.EmailAuthProvider;
|
||||
import com.google.firebase.auth.FacebookAuthProvider;
|
||||
import com.google.firebase.auth.FirebaseAuthProvider;
|
||||
import com.google.firebase.auth.FirebaseUser;
|
||||
import com.google.firebase.auth.FirebaseUserMetadata;
|
||||
import com.google.firebase.auth.GetTokenResult;
|
||||
import com.google.firebase.auth.GithubAuthProvider;
|
||||
import com.google.firebase.auth.GoogleAuthProvider;
|
||||
import com.google.firebase.auth.MultiFactorInfo;
|
||||
import com.google.firebase.auth.OAuthCredential;
|
||||
import com.google.firebase.auth.OAuthProvider;
|
||||
import com.google.firebase.auth.PhoneAuthProvider;
|
||||
import com.google.firebase.auth.PhoneMultiFactorInfo;
|
||||
import com.google.firebase.auth.PlayGamesAuthProvider;
|
||||
import com.google.firebase.auth.TwitterAuthProvider;
|
||||
import com.google.firebase.auth.UserInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class PigeonParser {
|
||||
static List<Object> manuallyToList(
|
||||
GeneratedAndroidFirebaseAuth.InternalUserDetails pigeonUserDetails) {
|
||||
List<Object> output = new ArrayList<>();
|
||||
output.add(pigeonUserDetails.getUserInfo().toList());
|
||||
output.add(pigeonUserDetails.getProviderData());
|
||||
return output;
|
||||
}
|
||||
|
||||
static GeneratedAndroidFirebaseAuth.InternalUserCredential parseAuthResult(
|
||||
@NonNull AuthResult authResult) {
|
||||
GeneratedAndroidFirebaseAuth.InternalUserCredential.Builder builder =
|
||||
new GeneratedAndroidFirebaseAuth.InternalUserCredential.Builder();
|
||||
|
||||
builder.setAdditionalUserInfo(parseAdditionalUserInfo(authResult.getAdditionalUserInfo()));
|
||||
builder.setCredential(parseAuthCredential(authResult.getCredential()));
|
||||
builder.setUser(parseFirebaseUser(authResult.getUser()));
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static GeneratedAndroidFirebaseAuth.InternalAdditionalUserInfo parseAdditionalUserInfo(
|
||||
AdditionalUserInfo additionalUserInfo) {
|
||||
if (additionalUserInfo == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
GeneratedAndroidFirebaseAuth.InternalAdditionalUserInfo.Builder builder =
|
||||
new GeneratedAndroidFirebaseAuth.InternalAdditionalUserInfo.Builder();
|
||||
|
||||
builder.setIsNewUser(additionalUserInfo.isNewUser());
|
||||
builder.setProfile(additionalUserInfo.getProfile());
|
||||
builder.setProviderId(additionalUserInfo.getProviderId());
|
||||
builder.setUsername(additionalUserInfo.getUsername());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static GeneratedAndroidFirebaseAuth.InternalAuthCredential parseAuthCredential(
|
||||
AuthCredential authCredential) {
|
||||
if (authCredential == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int authCredentialHashCode = authCredential.hashCode();
|
||||
FlutterFirebaseAuthPlugin.authCredentials.put(authCredentialHashCode, authCredential);
|
||||
|
||||
GeneratedAndroidFirebaseAuth.InternalAuthCredential.Builder builder =
|
||||
new GeneratedAndroidFirebaseAuth.InternalAuthCredential.Builder();
|
||||
|
||||
builder.setProviderId(authCredential.getProvider());
|
||||
builder.setSignInMethod(authCredential.getSignInMethod());
|
||||
builder.setNativeId((long) authCredentialHashCode);
|
||||
if (authCredential instanceof OAuthCredential) {
|
||||
builder.setAccessToken(((OAuthCredential) authCredential).getAccessToken());
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static GeneratedAndroidFirebaseAuth.InternalUserDetails parseFirebaseUser(
|
||||
FirebaseUser firebaseUser) {
|
||||
if (firebaseUser == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
GeneratedAndroidFirebaseAuth.InternalUserDetails.Builder builder =
|
||||
new GeneratedAndroidFirebaseAuth.InternalUserDetails.Builder();
|
||||
|
||||
GeneratedAndroidFirebaseAuth.InternalUserInfo.Builder builderInfo =
|
||||
new GeneratedAndroidFirebaseAuth.InternalUserInfo.Builder();
|
||||
|
||||
builderInfo.setDisplayName(firebaseUser.getDisplayName());
|
||||
builderInfo.setEmail(firebaseUser.getEmail());
|
||||
builderInfo.setIsEmailVerified(firebaseUser.isEmailVerified());
|
||||
builderInfo.setIsAnonymous(firebaseUser.isAnonymous());
|
||||
|
||||
final FirebaseUserMetadata userMetadata = firebaseUser.getMetadata();
|
||||
if (userMetadata != null) {
|
||||
builderInfo.setCreationTimestamp(firebaseUser.getMetadata().getCreationTimestamp());
|
||||
builderInfo.setLastSignInTimestamp(firebaseUser.getMetadata().getLastSignInTimestamp());
|
||||
}
|
||||
builderInfo.setPhoneNumber(firebaseUser.getPhoneNumber());
|
||||
builderInfo.setPhotoUrl(parsePhotoUrl(firebaseUser.getPhotoUrl()));
|
||||
builderInfo.setUid(firebaseUser.getUid());
|
||||
builderInfo.setTenantId(firebaseUser.getTenantId());
|
||||
|
||||
builder.setUserInfo(builderInfo.build());
|
||||
builder.setProviderData(parseUserInfoList(firebaseUser.getProviderData()));
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static List<Map<Object, Object>> parseUserInfoList(
|
||||
List<? extends UserInfo> userInfoList) {
|
||||
List<Map<Object, Object>> output = new ArrayList<>();
|
||||
|
||||
if (userInfoList == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (UserInfo userInfo : new ArrayList<UserInfo>(userInfoList)) {
|
||||
if (userInfo == null) {
|
||||
continue;
|
||||
}
|
||||
if (!FirebaseAuthProvider.PROVIDER_ID.equals(userInfo.getProviderId())) {
|
||||
output.add(parseUserInfoToMap(userInfo));
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private static Map<Object, Object> parseUserInfoToMap(UserInfo userInfo) {
|
||||
Map<Object, Object> output = new HashMap<>();
|
||||
output.put("displayName", userInfo.getDisplayName());
|
||||
output.put("email", userInfo.getEmail());
|
||||
output.put("isEmailVerified", userInfo.isEmailVerified());
|
||||
output.put("phoneNumber", userInfo.getPhoneNumber());
|
||||
output.put("photoUrl", parsePhotoUrl(userInfo.getPhotoUrl()));
|
||||
// Can be null on Emulator
|
||||
output.put("uid", userInfo.getUid() == null ? "" : userInfo.getUid());
|
||||
output.put("providerId", userInfo.getProviderId());
|
||||
output.put("isAnonymous", false);
|
||||
return output;
|
||||
}
|
||||
|
||||
private static String parsePhotoUrl(Uri photoUri) {
|
||||
if (photoUri == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String photoUrl = photoUri.toString();
|
||||
|
||||
// Return null if the URL is an empty string
|
||||
return "".equals(photoUrl) ? null : photoUrl;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
static AuthCredential getCredential(Map<String, Object> credentialMap) {
|
||||
// If the credential map contains a token, it means a native one has been stored
|
||||
if (credentialMap.get(Constants.TOKEN) != null) {
|
||||
int token = ((Number) credentialMap.get(Constants.TOKEN)).intValue();
|
||||
AuthCredential credential = FlutterFirebaseAuthPlugin.authCredentials.get(token);
|
||||
|
||||
if (credential == null) {
|
||||
throw FlutterFirebaseAuthPluginException.invalidCredential();
|
||||
}
|
||||
|
||||
return credential;
|
||||
}
|
||||
|
||||
String signInMethod =
|
||||
(String) Objects.requireNonNull(credentialMap.get(Constants.SIGN_IN_METHOD));
|
||||
String secret = (String) credentialMap.get(Constants.SECRET);
|
||||
String idToken = (String) credentialMap.get(Constants.ID_TOKEN);
|
||||
String accessToken = (String) credentialMap.get(Constants.ACCESS_TOKEN);
|
||||
String rawNonce = (String) credentialMap.get(Constants.RAW_NONCE);
|
||||
|
||||
switch (signInMethod) {
|
||||
case Constants.SIGN_IN_METHOD_PASSWORD:
|
||||
return EmailAuthProvider.getCredential(
|
||||
(String) Objects.requireNonNull(credentialMap.get(Constants.EMAIL)),
|
||||
Objects.requireNonNull(secret));
|
||||
case Constants.SIGN_IN_METHOD_EMAIL_LINK:
|
||||
return EmailAuthProvider.getCredentialWithLink(
|
||||
(String) Objects.requireNonNull(credentialMap.get(Constants.EMAIL)),
|
||||
(String) Objects.requireNonNull(credentialMap.get(Constants.EMAIL_LINK)));
|
||||
case Constants.SIGN_IN_METHOD_FACEBOOK:
|
||||
return FacebookAuthProvider.getCredential(Objects.requireNonNull(accessToken));
|
||||
case Constants.SIGN_IN_METHOD_GOOGLE:
|
||||
return GoogleAuthProvider.getCredential(idToken, accessToken);
|
||||
case Constants.SIGN_IN_METHOD_TWITTER:
|
||||
return TwitterAuthProvider.getCredential(
|
||||
Objects.requireNonNull(accessToken), Objects.requireNonNull(secret));
|
||||
case Constants.SIGN_IN_METHOD_GITHUB:
|
||||
return GithubAuthProvider.getCredential(Objects.requireNonNull(accessToken));
|
||||
case Constants.SIGN_IN_METHOD_PHONE:
|
||||
{
|
||||
String verificationId =
|
||||
(String) Objects.requireNonNull(credentialMap.get(Constants.VERIFICATION_ID));
|
||||
String smsCode = (String) Objects.requireNonNull(credentialMap.get(Constants.SMS_CODE));
|
||||
return PhoneAuthProvider.getCredential(verificationId, smsCode);
|
||||
}
|
||||
case Constants.SIGN_IN_METHOD_OAUTH:
|
||||
{
|
||||
String providerId =
|
||||
(String) Objects.requireNonNull(credentialMap.get(Constants.PROVIDER_ID));
|
||||
OAuthProvider.CredentialBuilder builder = OAuthProvider.newCredentialBuilder(providerId);
|
||||
if (accessToken != null) {
|
||||
builder.setAccessToken(accessToken);
|
||||
}
|
||||
if (rawNonce == null) {
|
||||
builder.setIdToken(Objects.requireNonNull(idToken));
|
||||
} else {
|
||||
builder.setIdTokenWithRawNonce(Objects.requireNonNull(idToken), rawNonce);
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
case Constants.SIGN_IN_METHOD_PLAY_GAMES:
|
||||
{
|
||||
String serverAuthCode =
|
||||
(String) Objects.requireNonNull(credentialMap.get(Constants.SERVER_AUTH_CODE));
|
||||
return PlayGamesAuthProvider.getCredential(serverAuthCode);
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static ActionCodeSettings getActionCodeSettings(
|
||||
@NonNull GeneratedAndroidFirebaseAuth.InternalActionCodeSettings pigeonActionCodeSettings) {
|
||||
ActionCodeSettings.Builder builder = ActionCodeSettings.newBuilder();
|
||||
|
||||
builder.setUrl(pigeonActionCodeSettings.getUrl());
|
||||
|
||||
if (pigeonActionCodeSettings.getDynamicLinkDomain() != null) {
|
||||
builder.setDynamicLinkDomain(pigeonActionCodeSettings.getDynamicLinkDomain());
|
||||
}
|
||||
|
||||
if (pigeonActionCodeSettings.getLinkDomain() != null) {
|
||||
builder.setLinkDomain(pigeonActionCodeSettings.getLinkDomain());
|
||||
}
|
||||
|
||||
builder.setHandleCodeInApp(pigeonActionCodeSettings.getHandleCodeInApp());
|
||||
|
||||
if (pigeonActionCodeSettings.getAndroidPackageName() != null) {
|
||||
builder.setAndroidPackageName(
|
||||
pigeonActionCodeSettings.getAndroidPackageName(),
|
||||
pigeonActionCodeSettings.getAndroidInstallApp(),
|
||||
pigeonActionCodeSettings.getAndroidMinimumVersion());
|
||||
}
|
||||
|
||||
if (pigeonActionCodeSettings.getIOSBundleId() != null) {
|
||||
builder.setIOSBundleId(pigeonActionCodeSettings.getIOSBundleId());
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static List<GeneratedAndroidFirebaseAuth.InternalMultiFactorInfo> multiFactorInfoToPigeon(
|
||||
List<MultiFactorInfo> hints) {
|
||||
List<GeneratedAndroidFirebaseAuth.InternalMultiFactorInfo> pigeonHints = new ArrayList<>();
|
||||
for (MultiFactorInfo info : hints) {
|
||||
if (info instanceof PhoneMultiFactorInfo) {
|
||||
pigeonHints.add(
|
||||
new GeneratedAndroidFirebaseAuth.InternalMultiFactorInfo.Builder()
|
||||
.setPhoneNumber(((PhoneMultiFactorInfo) info).getPhoneNumber())
|
||||
.setDisplayName(info.getDisplayName())
|
||||
.setEnrollmentTimestamp((double) info.getEnrollmentTimestamp())
|
||||
.setUid(info.getUid())
|
||||
.setFactorId(info.getFactorId())
|
||||
.build());
|
||||
|
||||
} else {
|
||||
pigeonHints.add(
|
||||
new GeneratedAndroidFirebaseAuth.InternalMultiFactorInfo.Builder()
|
||||
.setDisplayName(info.getDisplayName())
|
||||
.setEnrollmentTimestamp((double) info.getEnrollmentTimestamp())
|
||||
.setUid(info.getUid())
|
||||
.setFactorId(info.getFactorId())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
return pigeonHints;
|
||||
}
|
||||
|
||||
static List<List<Object>> multiFactorInfoToMap(List<MultiFactorInfo> hints) {
|
||||
List<List<Object>> pigeonHints = new ArrayList<>();
|
||||
for (GeneratedAndroidFirebaseAuth.InternalMultiFactorInfo info :
|
||||
multiFactorInfoToPigeon(hints)) {
|
||||
pigeonHints.add(info.toList());
|
||||
}
|
||||
return pigeonHints;
|
||||
}
|
||||
|
||||
static GeneratedAndroidFirebaseAuth.InternalActionCodeInfo parseActionCodeResult(
|
||||
@NonNull ActionCodeResult actionCodeResult) {
|
||||
GeneratedAndroidFirebaseAuth.InternalActionCodeInfo.Builder builder =
|
||||
new GeneratedAndroidFirebaseAuth.InternalActionCodeInfo.Builder();
|
||||
GeneratedAndroidFirebaseAuth.InternalActionCodeInfoData.Builder builderData =
|
||||
new GeneratedAndroidFirebaseAuth.InternalActionCodeInfoData.Builder();
|
||||
|
||||
int operation = actionCodeResult.getOperation();
|
||||
|
||||
switch (operation) {
|
||||
case ActionCodeResult.PASSWORD_RESET:
|
||||
builder.setOperation(GeneratedAndroidFirebaseAuth.ActionCodeInfoOperation.PASSWORD_RESET);
|
||||
break;
|
||||
case ActionCodeResult.VERIFY_EMAIL:
|
||||
builder.setOperation(GeneratedAndroidFirebaseAuth.ActionCodeInfoOperation.VERIFY_EMAIL);
|
||||
break;
|
||||
case ActionCodeResult.RECOVER_EMAIL:
|
||||
builder.setOperation(GeneratedAndroidFirebaseAuth.ActionCodeInfoOperation.RECOVER_EMAIL);
|
||||
break;
|
||||
case ActionCodeResult.SIGN_IN_WITH_EMAIL_LINK:
|
||||
builder.setOperation(GeneratedAndroidFirebaseAuth.ActionCodeInfoOperation.EMAIL_SIGN_IN);
|
||||
break;
|
||||
case ActionCodeResult.VERIFY_BEFORE_CHANGE_EMAIL:
|
||||
builder.setOperation(
|
||||
GeneratedAndroidFirebaseAuth.ActionCodeInfoOperation.VERIFY_AND_CHANGE_EMAIL);
|
||||
break;
|
||||
case ActionCodeResult.REVERT_SECOND_FACTOR_ADDITION:
|
||||
builder.setOperation(
|
||||
GeneratedAndroidFirebaseAuth.ActionCodeInfoOperation.REVERT_SECOND_FACTOR_ADDITION);
|
||||
break;
|
||||
}
|
||||
|
||||
ActionCodeInfo actionCodeInfo = actionCodeResult.getInfo();
|
||||
|
||||
if (actionCodeInfo != null && operation == ActionCodeResult.VERIFY_EMAIL
|
||||
|| operation == ActionCodeResult.PASSWORD_RESET) {
|
||||
builderData.setEmail(actionCodeInfo.getEmail());
|
||||
} else if (operation == ActionCodeResult.RECOVER_EMAIL
|
||||
|| operation == ActionCodeResult.VERIFY_BEFORE_CHANGE_EMAIL) {
|
||||
ActionCodeEmailInfo actionCodeEmailInfo =
|
||||
(ActionCodeEmailInfo) Objects.requireNonNull(actionCodeInfo);
|
||||
builderData.setEmail(actionCodeEmailInfo.getEmail());
|
||||
builderData.setPreviousEmail(actionCodeEmailInfo.getPreviousEmail());
|
||||
}
|
||||
|
||||
builder.setData(builderData.build());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static GeneratedAndroidFirebaseAuth.InternalIdTokenResult parseTokenResult(
|
||||
@NonNull GetTokenResult tokenResult) {
|
||||
final GeneratedAndroidFirebaseAuth.InternalIdTokenResult.Builder builder =
|
||||
new GeneratedAndroidFirebaseAuth.InternalIdTokenResult.Builder();
|
||||
|
||||
builder.setToken(tokenResult.getToken());
|
||||
builder.setSignInProvider(tokenResult.getSignInProvider());
|
||||
builder.setAuthTimestamp(tokenResult.getAuthTimestamp() * 1000);
|
||||
builder.setExpirationTimestamp(tokenResult.getExpirationTimestamp() * 1000);
|
||||
builder.setIssuedAtTimestamp(tokenResult.getIssuedAtTimestamp() * 1000);
|
||||
builder.setClaims(tokenResult.getClaims());
|
||||
builder.setSignInSecondFactor(tokenResult.getSignInSecondFactor());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
|
||||
String libraryVersionName = "UNKNOWN"
|
||||
String libraryName = "flutter-fire-auth"
|
||||
File pubspec = new File(project.projectDir.parentFile, 'pubspec.yaml')
|
||||
|
||||
if (pubspec.exists()) {
|
||||
String yaml = pubspec.text
|
||||
// Using \s*['|"]?([^\n|'|"]*)['|"]? to extract version number.
|
||||
Matcher versionMatcher = Pattern.compile("^version:\\s*['|\"]?([^\\n|'|\"]*)['|\"]?\$", Pattern.MULTILINE).matcher(yaml)
|
||||
if (versionMatcher.find()) libraryVersionName = versionMatcher.group(1).replaceAll("\\+", "-")
|
||||
}
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
// BuildConfig.VERSION_NAME
|
||||
buildConfigField 'String', 'LIBRARY_VERSION', "\"${libraryVersionName}\""
|
||||
// BuildConfig.LIBRARY_NAME
|
||||
buildConfigField 'String', 'LIBRARY_NAME', "\"${libraryName}\""
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
# Firebase Auth Example
|
||||
|
||||
[](https://pub.dev/packages/firebase_auth)
|
||||
|
||||
Demonstrates how to use the `firebase_auth` plugin and enable multiple auth providers.
|
||||
|
||||
## Phone Auth
|
||||
|
||||
1. Enable phone authentication in the [Firebase console]((https://console.firebase.google.com/u/0/project/_/authentication/providers)).
|
||||
2. Add test phone number and verification code to the Firebase console.
|
||||
- For this sample the number `+1 408-555-6969` and verification code `888888` are used.
|
||||
3. For iOS set the `URL Schemes` to the `REVERSE_CLIENT_ID` from the `GoogleServices-Info.plist` file.
|
||||
4. Enter the phone number `+1 408-555-6969` and press the `Verify phone number` button.
|
||||
5. Once the phone number is verified the app displays the test
|
||||
verification code.
|
||||
6. Enter the verficication code `888888` and press "Sign in with phone number"
|
||||
7. Signed in user ID is now displayed in the UI.
|
||||
|
||||
## Google Sign-In
|
||||
|
||||
1. Enable Google authentication in the [Firebase console](https://console.firebase.google.com/u/0/project/_/authentication/providers).
|
||||
2. For Android, add your app's package name and SHA-1 fingerprint to the [Settings page](https://console.firebase.google.com/project/_/settings/general) of the Firebase console. Refer to [Authenticating Your Client]('https://developers.google.com/android/guides/client-auth') for details on how to get your app's SHA-1 fingerprint.
|
||||
3. For iOS set the `URL Schemes` to the `REVERSE_CLIENT_ID` from the `GoogleServices-Info.plist` file (same step for `Phone Auth` above).
|
||||
4. Select `Google` under `Social Authentication` and click the `Sign In With Google` button.
|
||||
5. Signed in user's details are displayed in the UI.
|
||||
|
||||
### Running on Web
|
||||
|
||||
Make sure you run the example app on port 5000, since `localhost:5000` is
|
||||
whitelisted for Google authentication. To do so, run:
|
||||
|
||||
```
|
||||
flutter run -d web-server --web-port 5000
|
||||
```
|
||||
|
||||
## GitHub Sign-In
|
||||
To get your `clientId` and `clientSecret`:
|
||||
1. Visit https://github.com/settings/developers.
|
||||
2. Create a new OAuth application.
|
||||
3. Set **Home Page URL** to `https://react-native-firebase-testing.firebaseapp.com`.
|
||||
4. Set **Authorization callback URL** to `https://react-native-firebase-testing.firebaseapp.com/__/auth/handler`.
|
||||
5. After you register your app, add the `clientId` and `clientSecret` to the example app config in [`lib/config.dart`](./lib/config.dart).
|
||||
|
||||
## Twitter Sign-In
|
||||
Twitter sign in requires you to add keys from Twitter Developer API to Firebase Console, which means you cannot use the provided configurations with the example app, instead, **please create a new Firebase project**, then enable Twitter as an Auth provider (*optionally you can enable the rest of providers supported in this example*).
|
||||
|
||||
To get your `apiKey` and `apiSecretKey` for Twitter:
|
||||
1. Sign up for a developer account on [Twitter Developer](https://developer.twitter.com).
|
||||
2. Create a new app and copy your keys.
|
||||
3. From the dashboard, go to your app settings, then go to OAuth settings and turn on OAuth 1.0a, then add 2 callback URLs:
|
||||
1. `flutterfireauth://`
|
||||
2. `https://react-native-firebase-testing.firebaseapp.com/__/auth/handler`
|
||||
4. Add your keys to the example app config in [`lib/config.dart`](./lib/config.dart).
|
||||
|
||||
## Getting Started
|
||||
|
||||
For help getting started with Flutter, view the online
|
||||
[documentation](https://flutter.dev/).
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
include: ../../../../analysis_options.yaml
|
||||
|
||||
linter:
|
||||
rules:
|
||||
avoid_print: false
|
||||
depend_on_referenced_packages: false
|
||||
library_private_types_in_public_api: false
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
plugins {
|
||||
id "com.android.application"
|
||||
// START: FlutterFire Configuration
|
||||
id 'com.google.gms.google-services'
|
||||
// END: FlutterFire Configuration
|
||||
id "kotlin-android"
|
||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||
id "dev.flutter.flutter-gradle-plugin"
|
||||
}
|
||||
|
||||
def localProperties = new Properties()
|
||||
def localPropertiesFile = rootProject.file("local.properties")
|
||||
if (localPropertiesFile.exists()) {
|
||||
localPropertiesFile.withReader("UTF-8") { reader ->
|
||||
localProperties.load(reader)
|
||||
}
|
||||
}
|
||||
|
||||
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
|
||||
if (flutterVersionCode == null) {
|
||||
flutterVersionCode = "1"
|
||||
}
|
||||
|
||||
def flutterVersionName = localProperties.getProperty("flutter.versionName")
|
||||
if (flutterVersionName == null) {
|
||||
flutterVersionName = "1.0"
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.flutter.plugins.firebase.auth.example"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "io.flutter.plugins.firebase.auth.example"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
||||
minSdkVersion = flutter.minSdkVersion
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutterVersionCode.toInteger()
|
||||
versionName = flutterVersionName
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig = signingConfigs.debug
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
|
|
@ -0,0 +1,615 @@
|
|||
{
|
||||
"project_info": {
|
||||
"project_number": "406099696497",
|
||||
"firebase_url": "https://flutterfire-e2e-tests-default-rtdb.europe-west1.firebasedatabase.app",
|
||||
"project_id": "flutterfire-e2e-tests",
|
||||
"storage_bucket": "flutterfire-e2e-tests.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:d86a91cc7b338b233574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.analytics.example"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:a241c4b471513a203574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.appcheck.example"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-7bvmqp0fffe24vm2arng0dtdeh2tvkgl.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.appcheck.example",
|
||||
"certificate_hash": "909ca1482ef022bbae45a2db6b6d05d807a4c4aa"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:21d5142deea38dda3574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.auth.example"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-emmujnd7g2ammh5uu9ni6v04p4ateqac.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.auth.example",
|
||||
"certificate_hash": "5ad0d6d5cbe577ca185b8df246656bebc3957128"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-in8bfp0nali85oul1o98huoar6eo1vv1.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.auth.example",
|
||||
"certificate_hash": "909ca1482ef022bbae45a2db6b6d05d807a4c4aa"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:3ef965ff044efc0b3574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.dataconnect.example"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:40da41183cb3d3ff3574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.dynamiclinksexample"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:175ea7a64b2faf5e3574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.firestore.example"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:7ca3394493cc601a3574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.functions.example"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-17qn06u8a0dc717u8ul7s49ampk13lul.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.functions.example",
|
||||
"certificate_hash": "a4256c0612686b336af6d138a5479b7dc1ee1af6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-tvtvuiqogct1gs1s6lh114jeps7hpjm5.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.functions.example",
|
||||
"certificate_hash": "909ca1482ef022bbae45a2db6b6d05d807a4c4aa"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:6d1c1fbf4688f39c3574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.installations.example"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:74ebb073d7727cd43574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.messaging.example"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:f54b85cfa36a39f73574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.remoteconfig.example"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:0d4ed619c031c0ac3574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.tests"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-ib9hj9281l3343cm3nfvvdotaojrthdc.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.tests",
|
||||
"certificate_hash": "5ad0d6d5cbe577ca185b8df246656bebc3957128"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-lc54d5l8sp90k39r0bb39ovsgo1s9bek.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "io.flutter.plugins.firebase.tests",
|
||||
"certificate_hash": "909ca1482ef022bbae45a2db6b6d05d807a4c4aa"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:899c6485cfce26c13574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebase_ui_example"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-ltgvphphcckosvqhituel5km2k3aecg8.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "io.flutter.plugins.firebase_ui_example",
|
||||
"certificate_hash": "a4256c0612686b336af6d138a5479b7dc1ee1af6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:bc0b12b0605df8633574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebasecoreexample"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:0f3f7bfe78b8b7103574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebasecrashlyticsexample"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:406099696497:android:2751af6868a69f073574d0",
|
||||
"android_client_info": {
|
||||
"package_name": "io.flutter.plugins.firebasestorageexample"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "406099696497-a12gakvts4epfk5pkio7dphc1anjiggc.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
},
|
||||
{
|
||||
"client_id": "406099696497-0mofiof3ofcgmpmirb6q0fllvb372sme.apps.googleusercontent.com",
|
||||
"client_type": 2,
|
||||
"ios_info": {
|
||||
"bundle_id": "io.flutter.plugins.firebase.example"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application
|
||||
android:label="example"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:taskAffinity=""
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||
the Android process has started. This theme is visible to the user
|
||||
while the Flutter UI initializes. After that, this theme continues
|
||||
to determine the Window background behind the Flutter UI. -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
/>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
</application>
|
||||
<!-- Required to query activities that can process text, see:
|
||||
https://developer.android.com/training/package-visibility and
|
||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||
|
||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||
<data android:mimeType="text/plain"/>
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package io.flutter.plugins.firebase.auth.example
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
class MainActivity : FlutterActivity()
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
After Width: | Height: | Size: 544 B |
|
After Width: | Height: | Size: 442 B |
|
After Width: | Height: | Size: 721 B |
|
After Width: | Height: | Size: 1 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.buildDir = "../build"
|
||||
subprojects {
|
||||
project.buildDir = "${rootProject.buildDir}/${project.name}"
|
||||
}
|
||||
subprojects {
|
||||
project.evaluationDependsOn(":app")
|
||||
}
|
||||
|
||||
tasks.register("clean", Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
pluginManagement {
|
||||
def flutterSdkPath = {
|
||||
def properties = new Properties()
|
||||
file("local.properties").withInputStream { properties.load(it) }
|
||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||
return flutterSdkPath
|
||||
}()
|
||||
|
||||
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.3.0" apply false
|
||||
// START: FlutterFire Configuration
|
||||
id "com.google.gms.google-services" version "4.3.15" apply false
|
||||
// END: FlutterFire Configuration
|
||||
id "org.jetbrains.kotlin.android" version "1.9.22" apply false
|
||||
}
|
||||
|
||||
include ":app"
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?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>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>App</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.flutter.flutter.app</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>App</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>12.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
# Uncomment this line to define a global platform for your project
|
||||
platform :ios, '15.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
project 'Runner', {
|
||||
'Debug' => :debug,
|
||||
'Profile' => :release,
|
||||
'Release' => :release,
|
||||
}
|
||||
|
||||
def flutter_root
|
||||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
|
||||
unless File.exist?(generated_xcode_build_settings_path)
|
||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
||||
end
|
||||
|
||||
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||
return matches[1].strip if matches
|
||||
end
|
||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
|
||||
end
|
||||
|
||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||
|
||||
flutter_ios_podfile_setup
|
||||
|
||||
target 'Runner' do
|
||||
use_frameworks!
|
||||
use_modular_headers!
|
||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
flutter_additional_ios_build_settings(target)
|
||||
end
|
||||
|
||||
installer.generated_projects.each do |project|
|
||||
project.targets.each do |target|
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,700 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
081BFEF7D2871CF6AC71DD05 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7B49E087B951778510D20936 /* GoogleService-Info.plist */; };
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
25A01FAE278D905100D1E790 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 25A01FAD278D905100D1E790 /* GoogleService-Info.plist */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
3DBDE9876E1D48FC8ED096A3 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E010D242A20C21968D02B7C9 /* Pods_Runner.framework */; };
|
||||
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
|
||||
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
|
||||
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin 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>"; };
|
||||
253804AE278DB662003BA2E2 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||
25A01FAD278D905100D1E790 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
2FB2202774601424C6393E3D /* 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>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
7B49E087B951778510D20936 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; 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; };
|
||||
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
E010D242A20C21968D02B7C9 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
ED172FD60C3CC14CD005C328 /* 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>"; };
|
||||
FD585EE39F3F8D58CFCE5419 /* 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>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
|
||||
3DBDE9876E1D48FC8ED096A3 /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
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 */,
|
||||
9C7F99B73919EAB4FA657D9E /* Pods */,
|
||||
7B49E087B951778510D20936 /* GoogleService-Info.plist */,
|
||||
DE500BC6E74EB524103D00CE /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146EF1CF9000F007C117D /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146F01CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
253804AE278DB662003BA2E2 /* Runner.entitlements */,
|
||||
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
|
||||
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||
25A01FAD278D905100D1E790 /* GoogleService-Info.plist */,
|
||||
97C147021CF9000F007C117D /* Info.plist */,
|
||||
97C146F11CF9000F007C117D /* Supporting Files */,
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146F11CF9000F007C117D /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146F21CF9000F007C117D /* main.m */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9C7F99B73919EAB4FA657D9E /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2FB2202774601424C6393E3D /* Pods-Runner.debug.xcconfig */,
|
||||
ED172FD60C3CC14CD005C328 /* Pods-Runner.release.xcconfig */,
|
||||
FD585EE39F3F8D58CFCE5419 /* Pods-Runner.profile.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DE500BC6E74EB524103D00CE /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E010D242A20C21968D02B7C9 /* Pods_Runner.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
AC2BD8C60F3AA720CEA78FA3 /* [CP] Check Pods Manifest.lock */,
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
3E42446041C78F434168F902 /* [CP] Embed Pods Frameworks */,
|
||||
7A855ADEADAAB6F658B535DB /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Runner;
|
||||
packageProductDependencies = (
|
||||
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
|
||||
);
|
||||
productName = Runner;
|
||||
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "The Chromium Authors";
|
||||
TargetAttributes = {
|
||||
97C146ED1CF9000F007C117D = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 97C146E51CF9000F007C117D;
|
||||
packageReferences = (
|
||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */,
|
||||
);
|
||||
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
97C146ED1CF9000F007C117D /* Runner */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||
25A01FAE278D905100D1E790 /* GoogleService-Info.plist in Resources */,
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||
081BFEF7D2871CF6AC71DD05 /* GoogleService-Info.plist in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||
);
|
||||
name = "Thin Binary";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||
};
|
||||
3E42446041C78F434168F902 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
|
||||
"${BUILT_PRODUCTS_DIR}/AppAuth/AppAuth.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseAppCheckInterop/FirebaseAppCheckInterop.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseAuth/FirebaseAuth.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseAuthInterop/FirebaseAuthInterop.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseCoreExtension/FirebaseCoreExtension.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseInstallations/FirebaseInstallations.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/GTMAppAuth/GTMAppAuth.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/GoogleDataTransport/GoogleDataTransport.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/GoogleSignIn/GoogleSignIn.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/RecaptchaInterop/RecaptchaInterop.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/flutter_facebook_auth/flutter_facebook_auth.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/flutter_secure_storage/flutter_secure_storage.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/path_provider_foundation/path_provider_foundation.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/shared_preferences_foundation/shared_preferences_foundation.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/FBAEMKit/FBAEMKit.framework/FBAEMKit",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework/FBSDKCoreKit",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/FBSDKCoreKit_Basics/FBSDKCoreKit_Basics.framework/FBSDKCoreKit_Basics",
|
||||
"${PODS_XCFRAMEWORKS_BUILD_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework/FBSDKLoginKit",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AppAuth.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAppCheckInterop.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAuth.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAuthInterop.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreExtension.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMAppAuth.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleDataTransport.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleSignIn.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RecaptchaInterop.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_facebook_auth.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_secure_storage.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_foundation.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_foundation.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBAEMKit.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKCoreKit_Basics.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBSDKLoginKit.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
7A855ADEADAAB6F658B535DB /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/firebase_messaging/firebase_messaging_Privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/google_sign_in_ios/google_sign_in_ios_privacy.bundle",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/firebase_messaging_Privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/google_sign_in_ios_privacy.bundle",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
AC2BD8C60F3AA720CEA78FA3 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
|
||||
97C146F31CF9000F007C117D /* main.m in Sources */,
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase 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;
|
||||
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;
|
||||
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;
|
||||
HEADER_SEARCH_PATHS = "\\\"${PODS_ROOT}/Headers\\\"";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.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;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = YYX2P3XVJ7;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firebase.auth.example;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
97C147031CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
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;
|
||||
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;
|
||||
HEADER_SEARCH_PATHS = "\\\"${PODS_ROOT}/Headers\\\"";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.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;
|
||||
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;
|
||||
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;
|
||||
HEADER_SEARCH_PATHS = "\\\"${PODS_ROOT}/Headers\\\"";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
97C147061CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = YYX2P3XVJ7;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firebase.auth.example;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147071CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = YYX2P3XVJ7;
|
||||
ENABLE_BITCODE = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firebase.auth.example;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
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 */
|
||||
|
||||
/* Begin XCLocalSwiftPackageReference section */
|
||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = {
|
||||
isa = XCLocalSwiftPackageReference;
|
||||
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
|
||||
};
|
||||
/* End XCLocalSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = FlutterGeneratedPluginSwiftPackage;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
<?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">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</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>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#import <Flutter/Flutter.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : FlutterAppDelegate
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#import "AppDelegate.h"
|
||||
#import "GeneratedPluginRegistrant.h"
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
[GeneratedPluginRegistrant registerWithRegistry:self];
|
||||
// Override point for customization after application launch.
|
||||
return [super application:application didFinishLaunchingWithOptions:launchOptions];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-20x20@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-20x20@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-40x40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-40x40@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-60x60@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-60x60@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-20x20@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-20x20@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-29x29@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-29x29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-40x40@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-40x40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-76x76@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-76x76@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "ios-marketing",
|
||||
"filename" : "Icon-App-1024x1024@1x.png",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 564 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 68 B |
|
After Width: | Height: | Size: 68 B |
|
After Width: | Height: | Size: 68 B |
|
|
@ -0,0 +1,5 @@
|
|||
# Launch Screen Assets
|
||||
|
||||
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
|
||||
|
||||
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?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>CLIENT_ID</key>
|
||||
<string>406099696497-134k3722m01rtrsklhf3b7k8sqa5r7in.apps.googleusercontent.com</string>
|
||||
<key>REVERSED_CLIENT_ID</key>
|
||||
<string>com.googleusercontent.apps.406099696497-134k3722m01rtrsklhf3b7k8sqa5r7in</string>
|
||||
<key>ANDROID_CLIENT_ID</key>
|
||||
<string>406099696497-17qn06u8a0dc717u8ul7s49ampk13lul.apps.googleusercontent.com</string>
|
||||
<key>API_KEY</key>
|
||||
<string>AIzaSyDooSUGSf63Ghq02_iIhtnmwMDs4HlWS6c</string>
|
||||
<key>GCM_SENDER_ID</key>
|
||||
<string>406099696497</string>
|
||||
<key>PLIST_VERSION</key>
|
||||
<string>1</string>
|
||||
<key>BUNDLE_ID</key>
|
||||
<string>io.flutter.plugins.firebase.auth.example</string>
|
||||
<key>PROJECT_ID</key>
|
||||
<string>flutterfire-e2e-tests</string>
|
||||
<key>STORAGE_BUCKET</key>
|
||||
<string>flutterfire-e2e-tests.appspot.com</string>
|
||||
<key>IS_ADS_ENABLED</key>
|
||||
<false></false>
|
||||
<key>IS_ANALYTICS_ENABLED</key>
|
||||
<false></false>
|
||||
<key>IS_APPINVITE_ENABLED</key>
|
||||
<true></true>
|
||||
<key>IS_GCM_ENABLED</key>
|
||||
<true></true>
|
||||
<key>IS_SIGNIN_ENABLED</key>
|
||||
<true></true>
|
||||
<key>GOOGLE_APP_ID</key>
|
||||
<string>1:406099696497:ios:58cbc26aca8e5cf83574d0</string>
|
||||
<key>DATABASE_URL</key>
|
||||
<string>https://flutterfire-e2e-tests-default-rtdb.europe-west1.firebasedatabase.app</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Firebase Auth Example</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>firebase_auth_example</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>FacebookAppID</key>
|
||||
<string>128693022464535</string>
|
||||
<!-- The Facebook client token should not be made public but this is a developer mode app with whitelisted user access -->
|
||||
<key>FacebookClientToken</key>
|
||||
<string>16dbbdf0cfb309034a6ad98ac2a21688</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>com.googleusercontent.apps.406099696497-134k3722m01rtrsklhf3b7k8sqa5r7in</string>
|
||||
<string>fb128693022464535</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<false/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UISceneClassName</key>
|
||||
<string>UIWindowScene</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>FlutterSceneDelegate</string>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>flutter</string>
|
||||
<key>UISceneStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1 @@
|
|||
#import "GeneratedPluginRegistrant.h"
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?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>aps-environment</key>
|
||||
<string>development</string>
|
||||
<key>com.apple.developer.applesignin</key>
|
||||
<array>
|
||||
<string>Default</string>
|
||||
</array>
|
||||
<key>com.apple.developer.game-center</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#import <Flutter/Flutter.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"file_generated_by": "FlutterFire CLI",
|
||||
"purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory",
|
||||
"GOOGLE_APP_ID": "1:406099696497:ios:58cbc26aca8e5cf83574d0",
|
||||
"FIREBASE_PROJECT_ID": "flutterfire-e2e-tests",
|
||||
"GCM_SENDER_ID": "406099696497"
|
||||
}
|
||||
|
|
@ -0,0 +1,748 @@
|
|||
// Copyright 2022, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:barcode_widget/barcode_widget.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:firebase_auth_example/main.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
|
||||
import 'package:flutter_signin_button/flutter_signin_button.dart';
|
||||
import 'package:google_sign_in/google_sign_in.dart';
|
||||
|
||||
typedef OAuthSignIn = void Function();
|
||||
|
||||
// If set to true, the app will request notification permissions to use
|
||||
// silent verification for SMS MFA instead of Recaptcha.
|
||||
const withSilentVerificationSMSMFA = true;
|
||||
|
||||
/// Helper class to show a snackbar using the passed context.
|
||||
class ScaffoldSnackbar {
|
||||
// ignore: public_member_api_docs
|
||||
ScaffoldSnackbar(this._context);
|
||||
|
||||
/// The scaffold of current context.
|
||||
factory ScaffoldSnackbar.of(BuildContext context) {
|
||||
return ScaffoldSnackbar(context);
|
||||
}
|
||||
|
||||
final BuildContext _context;
|
||||
|
||||
/// Helper method to show a SnackBar.
|
||||
void show(String message) {
|
||||
ScaffoldMessenger.of(_context)
|
||||
..hideCurrentSnackBar()
|
||||
..showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(message),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// The mode of the current auth session, either [AuthMode.login] or [AuthMode.register].
|
||||
// ignore: public_member_api_docs
|
||||
enum AuthMode { login, register, phone }
|
||||
|
||||
extension on AuthMode {
|
||||
String get label => this == AuthMode.login
|
||||
? 'Sign in'
|
||||
: this == AuthMode.phone
|
||||
? 'Sign in'
|
||||
: 'Register';
|
||||
}
|
||||
|
||||
/// Entrypoint example for various sign-in flows with Firebase.
|
||||
class AuthGate extends StatefulWidget {
|
||||
// ignore: public_member_api_docs
|
||||
const AuthGate({Key? key}) : super(key: key);
|
||||
static String? appleAuthorizationCode;
|
||||
@override
|
||||
State<StatefulWidget> createState() => _AuthGateState();
|
||||
}
|
||||
|
||||
class _AuthGateState extends State<AuthGate> {
|
||||
TextEditingController emailController = TextEditingController();
|
||||
TextEditingController passwordController = TextEditingController();
|
||||
TextEditingController phoneController = TextEditingController();
|
||||
|
||||
GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
String error = '';
|
||||
String verificationId = '';
|
||||
|
||||
AuthMode mode = AuthMode.login;
|
||||
|
||||
bool isLoading = false;
|
||||
|
||||
void setIsLoading() {
|
||||
setState(() {
|
||||
isLoading = !isLoading;
|
||||
});
|
||||
}
|
||||
|
||||
late Map<Buttons, OAuthSignIn> authButtons;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
if (withSilentVerificationSMSMFA && !kIsWeb) {
|
||||
FirebaseMessaging messaging = FirebaseMessaging.instance;
|
||||
messaging.requestPermission();
|
||||
}
|
||||
|
||||
if (!kIsWeb && Platform.isMacOS) {
|
||||
authButtons = {
|
||||
Buttons.Apple: () => _handleMultiFactorException(
|
||||
_signInWithApple,
|
||||
),
|
||||
};
|
||||
} else {
|
||||
authButtons = {
|
||||
Buttons.Apple: () => _handleMultiFactorException(
|
||||
_signInWithApple,
|
||||
),
|
||||
Buttons.Google: () => _handleMultiFactorException(
|
||||
_signInWithGoogle,
|
||||
),
|
||||
Buttons.GitHub: () => _handleMultiFactorException(
|
||||
_signInWithGitHub,
|
||||
),
|
||||
Buttons.Microsoft: () => _handleMultiFactorException(
|
||||
_signInWithMicrosoft,
|
||||
),
|
||||
Buttons.Twitter: () => _handleMultiFactorException(
|
||||
_signInWithTwitter,
|
||||
),
|
||||
Buttons.Yahoo: () => _handleMultiFactorException(
|
||||
_signInWithYahoo,
|
||||
),
|
||||
Buttons.Facebook: () => _handleMultiFactorException(
|
||||
_signInWithFacebook,
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: FocusScope.of(context).unfocus,
|
||||
child: Scaffold(
|
||||
body: Center(
|
||||
child: SingleChildScrollView(
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: SafeArea(
|
||||
child: Form(
|
||||
key: formKey,
|
||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 400),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Visibility(
|
||||
visible: error.isNotEmpty,
|
||||
child: MaterialBanner(
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.error,
|
||||
content: SelectableText(error),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
error = '';
|
||||
});
|
||||
},
|
||||
child: const Text(
|
||||
'dismiss',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
],
|
||||
contentTextStyle:
|
||||
const TextStyle(color: Colors.white),
|
||||
padding: const EdgeInsets.all(10),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
if (mode != AuthMode.phone)
|
||||
Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: emailController,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Email',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
autofillHints: const [AutofillHints.email],
|
||||
validator: (value) =>
|
||||
value != null && value.isNotEmpty
|
||||
? null
|
||||
: 'Required',
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextFormField(
|
||||
controller: passwordController,
|
||||
obscureText: true,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Password',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (value) =>
|
||||
value != null && value.isNotEmpty
|
||||
? null
|
||||
: 'Required',
|
||||
),
|
||||
],
|
||||
),
|
||||
if (mode == AuthMode.phone)
|
||||
TextFormField(
|
||||
controller: phoneController,
|
||||
decoration: const InputDecoration(
|
||||
hintText: '+12345678910',
|
||||
labelText: 'Phone number',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (value) =>
|
||||
value != null && value.isNotEmpty
|
||||
? null
|
||||
: 'Required',
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 50,
|
||||
child: ElevatedButton(
|
||||
onPressed: isLoading
|
||||
? null
|
||||
: () => _handleMultiFactorException(
|
||||
_emailAndPassword,
|
||||
),
|
||||
child: isLoading
|
||||
? const CircularProgressIndicator.adaptive()
|
||||
: Text(mode.label),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: _resetPassword,
|
||||
child: const Text('Forgot password?'),
|
||||
),
|
||||
...authButtons.keys
|
||||
.map(
|
||||
(button) => Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 5),
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: isLoading
|
||||
? Container(
|
||||
color: Colors.grey[200],
|
||||
height: 50,
|
||||
width: double.infinity,
|
||||
)
|
||||
: SizedBox(
|
||||
width: double.infinity,
|
||||
height: 50,
|
||||
child: SignInButton(
|
||||
button,
|
||||
onPressed: authButtons[button],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 50,
|
||||
child: OutlinedButton(
|
||||
onPressed: isLoading
|
||||
? null
|
||||
: () {
|
||||
if (mode != AuthMode.phone) {
|
||||
setState(() {
|
||||
mode = AuthMode.phone;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
mode = AuthMode.login;
|
||||
});
|
||||
}
|
||||
},
|
||||
child: isLoading
|
||||
? const CircularProgressIndicator.adaptive()
|
||||
: Text(
|
||||
mode != AuthMode.phone
|
||||
? 'Sign in with Phone Number'
|
||||
: 'Sign in with Email and Password',
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
if (mode != AuthMode.phone)
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
children: [
|
||||
TextSpan(
|
||||
text: mode == AuthMode.login
|
||||
? "Don't have an account? "
|
||||
: 'You have an account? ',
|
||||
),
|
||||
TextSpan(
|
||||
text: mode == AuthMode.login
|
||||
? 'Register now'
|
||||
: 'Click to login',
|
||||
style: const TextStyle(color: Colors.blue),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
setState(() {
|
||||
mode = mode == AuthMode.login
|
||||
? AuthMode.register
|
||||
: AuthMode.login;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
children: [
|
||||
const TextSpan(text: 'Or '),
|
||||
TextSpan(
|
||||
text: 'continue as guest',
|
||||
style: const TextStyle(color: Colors.blue),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = _anonymousAuth,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future _resetPassword() async {
|
||||
String? email;
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('Send'),
|
||||
),
|
||||
],
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text('Enter your email'),
|
||||
const SizedBox(height: 20),
|
||||
TextFormField(
|
||||
onChanged: (value) {
|
||||
email = value;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
if (email != null) {
|
||||
try {
|
||||
await auth.sendPasswordResetEmail(email: email!);
|
||||
ScaffoldSnackbar.of(context).show('Password reset email is sent');
|
||||
} catch (e) {
|
||||
ScaffoldSnackbar.of(context).show('Error resetting');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _anonymousAuth() async {
|
||||
setIsLoading();
|
||||
|
||||
try {
|
||||
await auth.signInAnonymously();
|
||||
} on FirebaseAuthException catch (e) {
|
||||
setState(() {
|
||||
error = '${e.message}';
|
||||
});
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
error = '$e';
|
||||
});
|
||||
} finally {
|
||||
setIsLoading();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _handleMultiFactorException(
|
||||
Future<void> Function() authFunction,
|
||||
) async {
|
||||
setIsLoading();
|
||||
try {
|
||||
await authFunction();
|
||||
} on FirebaseAuthMultiFactorException catch (e) {
|
||||
setState(() {
|
||||
error = '${e.message}';
|
||||
});
|
||||
final firstTotpHint = e.resolver.hints
|
||||
.firstWhereOrNull((element) => element is TotpMultiFactorInfo);
|
||||
if (firstTotpHint != null) {
|
||||
final code = await getSmsCodeFromUser(context);
|
||||
final assertion = await TotpMultiFactorGenerator.getAssertionForSignIn(
|
||||
firstTotpHint.uid,
|
||||
code!,
|
||||
);
|
||||
await e.resolver.resolveSignIn(assertion);
|
||||
return;
|
||||
}
|
||||
|
||||
final firstPhoneHint = e.resolver.hints
|
||||
.firstWhereOrNull((element) => element is PhoneMultiFactorInfo);
|
||||
|
||||
if (firstPhoneHint is! PhoneMultiFactorInfo) {
|
||||
return;
|
||||
}
|
||||
await auth.verifyPhoneNumber(
|
||||
multiFactorSession: e.resolver.session,
|
||||
multiFactorInfo: firstPhoneHint,
|
||||
verificationCompleted: (_) {},
|
||||
verificationFailed: print,
|
||||
codeSent: (String verificationId, int? resendToken) async {
|
||||
final smsCode = await getSmsCodeFromUser(context);
|
||||
|
||||
if (smsCode != null) {
|
||||
// Create a PhoneAuthCredential with the code
|
||||
final credential = PhoneAuthProvider.credential(
|
||||
verificationId: verificationId,
|
||||
smsCode: smsCode,
|
||||
);
|
||||
|
||||
try {
|
||||
await e.resolver.resolveSignIn(
|
||||
PhoneMultiFactorGenerator.getAssertion(
|
||||
credential,
|
||||
),
|
||||
);
|
||||
} on FirebaseAuthException catch (e) {
|
||||
print(e.message);
|
||||
}
|
||||
}
|
||||
},
|
||||
codeAutoRetrievalTimeout: print,
|
||||
);
|
||||
} on FirebaseAuthException catch (e) {
|
||||
setState(() {
|
||||
error = '${e.message}';
|
||||
});
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
error = '$e';
|
||||
});
|
||||
}
|
||||
setIsLoading();
|
||||
}
|
||||
|
||||
Future<void> _emailAndPassword() async {
|
||||
if (formKey.currentState?.validate() ?? false) {
|
||||
if (mode == AuthMode.login) {
|
||||
await auth.signInWithEmailAndPassword(
|
||||
email: emailController.text,
|
||||
password: passwordController.text,
|
||||
);
|
||||
} else if (mode == AuthMode.register) {
|
||||
await auth.createUserWithEmailAndPassword(
|
||||
email: emailController.text,
|
||||
password: passwordController.text,
|
||||
);
|
||||
} else {
|
||||
await _phoneAuth();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _phoneAuth() async {
|
||||
if (mode != AuthMode.phone) {
|
||||
setState(() {
|
||||
mode = AuthMode.phone;
|
||||
});
|
||||
} else {
|
||||
if (kIsWeb) {
|
||||
final confirmationResult =
|
||||
await auth.signInWithPhoneNumber(phoneController.text);
|
||||
final smsCode = await getSmsCodeFromUser(context);
|
||||
|
||||
if (smsCode != null) {
|
||||
await confirmationResult.confirm(smsCode);
|
||||
}
|
||||
} else {
|
||||
await auth.verifyPhoneNumber(
|
||||
phoneNumber: phoneController.text,
|
||||
verificationCompleted: (_) {},
|
||||
verificationFailed: (e) {
|
||||
setState(() {
|
||||
error = '${e.message}';
|
||||
});
|
||||
},
|
||||
codeSent: (String verificationId, int? resendToken) async {
|
||||
final smsCode = await getSmsCodeFromUser(context);
|
||||
|
||||
if (smsCode != null) {
|
||||
// Create a PhoneAuthCredential with the code
|
||||
final credential = PhoneAuthProvider.credential(
|
||||
verificationId: verificationId,
|
||||
smsCode: smsCode,
|
||||
);
|
||||
|
||||
try {
|
||||
// Sign the user in (or link) with the credential
|
||||
await auth.signInWithCredential(credential);
|
||||
} on FirebaseAuthException catch (e) {
|
||||
setState(() {
|
||||
error = e.message ?? '';
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
codeAutoRetrievalTimeout: (e) {
|
||||
setState(() {
|
||||
error = e;
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _signInWithGoogle() async {
|
||||
// Trigger the authentication flow
|
||||
final googleUser = await GoogleSignIn().signIn();
|
||||
|
||||
// Obtain the auth details from the request
|
||||
final googleAuth = await googleUser?.authentication;
|
||||
|
||||
if (googleAuth != null) {
|
||||
// Create a new credential
|
||||
final credential = GoogleAuthProvider.credential(
|
||||
accessToken: googleAuth.accessToken,
|
||||
idToken: googleAuth.idToken,
|
||||
);
|
||||
|
||||
// Once signed in, return the UserCredential
|
||||
await auth.signInWithCredential(credential);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _signInWithFacebook() async {
|
||||
// Trigger the authentication flow
|
||||
// by default we request the email and the public profile
|
||||
final LoginResult result = await FacebookAuth.instance.login();
|
||||
|
||||
if (result.status == LoginStatus.success) {
|
||||
// Get access token
|
||||
final AccessToken accessToken = result.accessToken!;
|
||||
|
||||
// Login with token
|
||||
await auth.signInWithCredential(
|
||||
FacebookAuthProvider.credential(accessToken.tokenString),
|
||||
);
|
||||
} else {
|
||||
print('Facebook login did not succeed');
|
||||
print(result.status);
|
||||
print(result.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _signInWithTwitter() async {
|
||||
TwitterAuthProvider twitterProvider = TwitterAuthProvider();
|
||||
|
||||
if (kIsWeb) {
|
||||
await auth.signInWithPopup(twitterProvider);
|
||||
} else {
|
||||
await auth.signInWithProvider(twitterProvider);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _signInWithApple() async {
|
||||
final appleProvider = AppleAuthProvider();
|
||||
appleProvider.addScope('email');
|
||||
|
||||
if (kIsWeb) {
|
||||
// Once signed in, return the UserCredential
|
||||
await auth.signInWithPopup(appleProvider);
|
||||
} else {
|
||||
final userCred = await auth.signInWithProvider(appleProvider);
|
||||
AuthGate.appleAuthorizationCode =
|
||||
userCred.additionalUserInfo?.authorizationCode;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _signInWithYahoo() async {
|
||||
final yahooProvider = YahooAuthProvider();
|
||||
|
||||
if (kIsWeb) {
|
||||
// Once signed in, return the UserCredential
|
||||
await auth.signInWithPopup(yahooProvider);
|
||||
} else {
|
||||
await auth.signInWithProvider(yahooProvider);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _signInWithGitHub() async {
|
||||
final githubProvider = GithubAuthProvider();
|
||||
|
||||
if (kIsWeb) {
|
||||
await auth.signInWithPopup(githubProvider);
|
||||
} else {
|
||||
await auth.signInWithProvider(githubProvider);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _signInWithMicrosoft() async {
|
||||
final microsoftProvider = MicrosoftAuthProvider();
|
||||
|
||||
if (kIsWeb) {
|
||||
await auth.signInWithPopup(microsoftProvider);
|
||||
} else {
|
||||
await auth.signInWithProvider(microsoftProvider);
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> getSmsCodeFromUser(BuildContext context) async {
|
||||
String? smsCode;
|
||||
|
||||
// Update the UI - wait for the user to enter the SMS code
|
||||
await showDialog<String>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text('SMS code:'),
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('Sign in'),
|
||||
),
|
||||
OutlinedButton(
|
||||
onPressed: () {
|
||||
smsCode = null;
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
],
|
||||
content: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: TextField(
|
||||
onChanged: (value) {
|
||||
smsCode = value;
|
||||
},
|
||||
textAlign: TextAlign.center,
|
||||
autofocus: true,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return smsCode;
|
||||
}
|
||||
|
||||
Future<String?> getTotpFromUser(
|
||||
BuildContext context,
|
||||
TotpSecret totpSecret,
|
||||
) async {
|
||||
String? smsCode;
|
||||
|
||||
final qrCodeUrl = await totpSecret.generateQrCodeUrl(
|
||||
accountName: FirebaseAuth.instance.currentUser!.email,
|
||||
issuer: 'Firebase',
|
||||
);
|
||||
|
||||
// Update the UI - wait for the user to enter the SMS code
|
||||
await showDialog<String>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text('TOTP code:'),
|
||||
content: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
BarcodeWidget(
|
||||
barcode: Barcode.qrCode(),
|
||||
data: qrCodeUrl,
|
||||
width: 150,
|
||||
height: 150,
|
||||
),
|
||||
TextField(
|
||||
onChanged: (value) {
|
||||
smsCode = value;
|
||||
},
|
||||
textAlign: TextAlign.center,
|
||||
autofocus: true,
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
totpSecret.openInOtpApp(qrCodeUrl);
|
||||
},
|
||||
child: const Text('Open in OTP App'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('Sign in'),
|
||||
),
|
||||
OutlinedButton(
|
||||
onPressed: () {
|
||||
smsCode = null;
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return smsCode;
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
// Copyright 2022, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// File generated by FlutterFire CLI.
|
||||
// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members
|
||||
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
|
||||
import 'package:flutter/foundation.dart'
|
||||
show defaultTargetPlatform, kIsWeb, TargetPlatform;
|
||||
|
||||
/// Default [FirebaseOptions] for use with your Firebase apps.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// import 'firebase_options.dart';
|
||||
/// // ...
|
||||
/// await Firebase.initializeApp(
|
||||
/// options: DefaultFirebaseOptions.currentPlatform,
|
||||
/// );
|
||||
/// ```
|
||||
class DefaultFirebaseOptions {
|
||||
static FirebaseOptions get currentPlatform {
|
||||
if (kIsWeb) {
|
||||
return web;
|
||||
}
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
return android;
|
||||
case TargetPlatform.iOS:
|
||||
return ios;
|
||||
case TargetPlatform.macOS:
|
||||
return macos;
|
||||
case TargetPlatform.windows:
|
||||
return macos;
|
||||
case TargetPlatform.linux:
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions have not been configured for linux - '
|
||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||
);
|
||||
default:
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions are not supported for this platform.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static const FirebaseOptions web = FirebaseOptions(
|
||||
apiKey: 'AIzaSyB7wZb2tO1-Fs6GbDADUSTs2Qs3w08Hovw',
|
||||
appId: '1:406099696497:web:87e25e51afe982cd3574d0',
|
||||
messagingSenderId: '406099696497',
|
||||
projectId: 'flutterfire-e2e-tests',
|
||||
authDomain: 'flutterfire-e2e-tests.firebaseapp.com',
|
||||
databaseURL:
|
||||
'https://flutterfire-e2e-tests-default-rtdb.europe-west1.firebasedatabase.app',
|
||||
storageBucket: 'flutterfire-e2e-tests.appspot.com',
|
||||
measurementId: 'G-JN95N1JV2E',
|
||||
);
|
||||
|
||||
static const FirebaseOptions android = FirebaseOptions(
|
||||
apiKey: 'AIzaSyCdRjCVZlhrq72RuEklEyyxYlBRCYhI2Sw',
|
||||
appId: '1:406099696497:android:21d5142deea38dda3574d0',
|
||||
messagingSenderId: '406099696497',
|
||||
projectId: 'flutterfire-e2e-tests',
|
||||
databaseURL:
|
||||
'https://flutterfire-e2e-tests-default-rtdb.europe-west1.firebasedatabase.app',
|
||||
storageBucket: 'flutterfire-e2e-tests.appspot.com',
|
||||
);
|
||||
|
||||
static const FirebaseOptions ios = FirebaseOptions(
|
||||
apiKey: 'AIzaSyDooSUGSf63Ghq02_iIhtnmwMDs4HlWS6c',
|
||||
appId: '1:406099696497:ios:58cbc26aca8e5cf83574d0',
|
||||
messagingSenderId: '406099696497',
|
||||
projectId: 'flutterfire-e2e-tests',
|
||||
databaseURL:
|
||||
'https://flutterfire-e2e-tests-default-rtdb.europe-west1.firebasedatabase.app',
|
||||
storageBucket: 'flutterfire-e2e-tests.appspot.com',
|
||||
androidClientId:
|
||||
'406099696497-17qn06u8a0dc717u8ul7s49ampk13lul.apps.googleusercontent.com',
|
||||
iosClientId:
|
||||
'406099696497-134k3722m01rtrsklhf3b7k8sqa5r7in.apps.googleusercontent.com',
|
||||
iosBundleId: 'io.flutter.plugins.firebase.auth.example',
|
||||
);
|
||||
|
||||
static const FirebaseOptions macos = FirebaseOptions(
|
||||
apiKey: 'AIzaSyDooSUGSf63Ghq02_iIhtnmwMDs4HlWS6c',
|
||||
appId: '1:406099696497:ios:58cbc26aca8e5cf83574d0',
|
||||
messagingSenderId: '406099696497',
|
||||
projectId: 'flutterfire-e2e-tests',
|
||||
databaseURL:
|
||||
'https://flutterfire-e2e-tests-default-rtdb.europe-west1.firebasedatabase.app',
|
||||
storageBucket: 'flutterfire-e2e-tests.appspot.com',
|
||||
androidClientId:
|
||||
'406099696497-17qn06u8a0dc717u8ul7s49ampk13lul.apps.googleusercontent.com',
|
||||
iosClientId:
|
||||
'406099696497-134k3722m01rtrsklhf3b7k8sqa5r7in.apps.googleusercontent.com',
|
||||
iosBundleId: 'io.flutter.plugins.firebase.auth.example',
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
// Copyright 2022, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_sign_in_dartio/google_sign_in_dartio.dart';
|
||||
|
||||
import 'auth.dart';
|
||||
import 'firebase_options.dart';
|
||||
import 'profile.dart';
|
||||
|
||||
/// Requires that a Firebase local emulator is running locally.
|
||||
/// See https://firebase.google.com/docs/auth/flutter/start#optional_prototype_and_test_with_firebase_local_emulator_suite
|
||||
bool shouldUseFirebaseEmulator = false;
|
||||
|
||||
late final FirebaseApp app;
|
||||
late final FirebaseAuth auth;
|
||||
|
||||
// Requires that the Firebase Auth emulator is running locally
|
||||
// e.g via `melos run firebase:emulator`.
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
// We're using the manual installation on non-web platforms since Google sign in plugin doesn't yet support Dart initialization.
|
||||
// See related issue: https://github.com/flutter/flutter/issues/96391
|
||||
|
||||
// We store the app and auth to make testing with a named instance easier.
|
||||
app = await Firebase.initializeApp(
|
||||
options: DefaultFirebaseOptions.currentPlatform,
|
||||
);
|
||||
auth = FirebaseAuth.instanceFor(app: app);
|
||||
|
||||
if (shouldUseFirebaseEmulator) {
|
||||
await auth.useAuthEmulator('localhost', 9099);
|
||||
}
|
||||
|
||||
if (!kIsWeb && Platform.isWindows) {
|
||||
await GoogleSignInDart.register(
|
||||
clientId:
|
||||
'406099696497-g5o9l0blii9970bgmfcfv14pioj90djd.apps.googleusercontent.com',
|
||||
);
|
||||
}
|
||||
|
||||
runApp(const AuthExampleApp());
|
||||
}
|
||||
|
||||
/// The entry point of the application.
|
||||
///
|
||||
/// Returns a [MaterialApp].
|
||||
class AuthExampleApp extends StatelessWidget {
|
||||
const AuthExampleApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Firebase Example App',
|
||||
theme: ThemeData(primarySwatch: Colors.amber),
|
||||
home: Scaffold(
|
||||
body: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
return Row(
|
||||
children: [
|
||||
Visibility(
|
||||
visible: constraints.maxWidth >= 1200,
|
||||
child: Expanded(
|
||||
child: Container(
|
||||
height: double.infinity,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Firebase Auth Desktop',
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: constraints.maxWidth >= 1200
|
||||
? constraints.maxWidth / 2
|
||||
: constraints.maxWidth,
|
||||
child: StreamBuilder<User?>(
|
||||
stream: auth.authStateChanges(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
return const ProfilePage();
|
||||
}
|
||||
return const AuthGate();
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,391 @@
|
|||
// Copyright 2022, the Chromium project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:firebase_auth_example/main.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_sign_in/google_sign_in.dart';
|
||||
|
||||
import 'auth.dart';
|
||||
|
||||
/// Displayed as a profile image if the user doesn't have one.
|
||||
const placeholderImage =
|
||||
'https://upload.wikimedia.org/wikipedia/commons/c/cd/Portrait_Placeholder_Square.png';
|
||||
|
||||
/// Profile page shows after sign in or registration.
|
||||
class ProfilePage extends StatefulWidget {
|
||||
// ignore: public_member_api_docs
|
||||
const ProfilePage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
// ignore: library_private_types_in_public_api
|
||||
_ProfilePageState createState() => _ProfilePageState();
|
||||
}
|
||||
|
||||
class _ProfilePageState extends State<ProfilePage> {
|
||||
late User user;
|
||||
late TextEditingController controller;
|
||||
final phoneController = TextEditingController();
|
||||
|
||||
String? photoURL;
|
||||
|
||||
bool showSaveButton = false;
|
||||
bool isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
user = auth.currentUser!;
|
||||
controller = TextEditingController(text: user.displayName);
|
||||
|
||||
controller.addListener(_onNameChanged);
|
||||
|
||||
auth.userChanges().listen((event) {
|
||||
if (event != null && mounted) {
|
||||
setState(() {
|
||||
user = event;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
log(user.toString());
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
controller.removeListener(_onNameChanged);
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void setIsLoading() {
|
||||
setState(() {
|
||||
isLoading = !isLoading;
|
||||
});
|
||||
}
|
||||
|
||||
void _onNameChanged() {
|
||||
setState(() {
|
||||
if (controller.text == user.displayName || controller.text.isEmpty) {
|
||||
showSaveButton = false;
|
||||
} else {
|
||||
showSaveButton = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Map User provider data into a list of Provider Ids.
|
||||
List get userProviders => user.providerData.map((e) => e.providerId).toList();
|
||||
|
||||
Future updateDisplayName() async {
|
||||
await user.updateDisplayName(controller.text);
|
||||
|
||||
setState(() {
|
||||
showSaveButton = false;
|
||||
});
|
||||
|
||||
// ignore: use_build_context_synchronously
|
||||
ScaffoldSnackbar.of(context).show('Name updated');
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: FocusScope.of(context).unfocus,
|
||||
child: Scaffold(
|
||||
body: Stack(
|
||||
children: [
|
||||
Center(
|
||||
child: SizedBox(
|
||||
width: 400,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
maxRadius: 60,
|
||||
backgroundImage: NetworkImage(
|
||||
user.photoURL ?? placeholderImage,
|
||||
),
|
||||
),
|
||||
Positioned.directional(
|
||||
textDirection: Directionality.of(context),
|
||||
end: 0,
|
||||
bottom: 0,
|
||||
child: Material(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
borderRadius: BorderRadius.circular(40),
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
final photoURL = await getPhotoURLFromUser();
|
||||
|
||||
if (photoURL != null) {
|
||||
await user.updatePhotoURL(photoURL);
|
||||
}
|
||||
},
|
||||
radius: 50,
|
||||
child: const SizedBox(
|
||||
width: 35,
|
||||
height: 35,
|
||||
child: Icon(Icons.edit),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
TextField(
|
||||
textAlign: TextAlign.center,
|
||||
controller: controller,
|
||||
decoration: const InputDecoration(
|
||||
border: InputBorder.none,
|
||||
floatingLabelBehavior: FloatingLabelBehavior.never,
|
||||
alignLabelWithHint: true,
|
||||
label: Center(
|
||||
child: Text(
|
||||
'Click to add a display name',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(user.email ?? user.phoneNumber ?? 'User'),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (userProviders.contains('phone'))
|
||||
const Icon(Icons.phone),
|
||||
if (userProviders.contains('password'))
|
||||
const Icon(Icons.mail),
|
||||
if (userProviders.contains('google.com'))
|
||||
SizedBox(
|
||||
width: 24,
|
||||
child: Image.network(
|
||||
'https://upload.wikimedia.org/wikipedia/commons/0/09/IOS_Google_icon.png',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
user.sendEmailVerification();
|
||||
},
|
||||
child: const Text('Verify Email'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
final a = await user.multiFactor.getEnrolledFactors();
|
||||
print(a);
|
||||
},
|
||||
child: const Text('Get enrolled factors'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
if (AuthGate.appleAuthorizationCode != null) {
|
||||
// The `authorizationCode` is on the user credential.
|
||||
// e.g. final authorizationCode = userCredential.additionalUserInfo?.authorizationCode;
|
||||
await FirebaseAuth.instance
|
||||
.revokeTokenWithAuthorizationCode(
|
||||
AuthGate.appleAuthorizationCode!,
|
||||
);
|
||||
// You may wish to delete the user at this point
|
||||
AuthGate.appleAuthorizationCode = null;
|
||||
} else {
|
||||
print(
|
||||
'Apple `authorizationCode` is null, cannot revoke token.',
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const Text('Revoke Apple auth token'),
|
||||
),
|
||||
TextFormField(
|
||||
controller: phoneController,
|
||||
decoration: const InputDecoration(
|
||||
icon: Icon(Icons.phone),
|
||||
hintText: '+33612345678',
|
||||
labelText: 'Phone number',
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
final session = await user.multiFactor.getSession();
|
||||
await auth.verifyPhoneNumber(
|
||||
multiFactorSession: session,
|
||||
phoneNumber: phoneController.text,
|
||||
verificationCompleted: (_) {},
|
||||
verificationFailed: print,
|
||||
codeSent: (
|
||||
String verificationId,
|
||||
int? resendToken,
|
||||
) async {
|
||||
final smsCode = await getSmsCodeFromUser(context);
|
||||
|
||||
if (smsCode != null) {
|
||||
// Create a PhoneAuthCredential with the code
|
||||
final credential = PhoneAuthProvider.credential(
|
||||
verificationId: verificationId,
|
||||
smsCode: smsCode,
|
||||
);
|
||||
|
||||
try {
|
||||
await user.multiFactor.enroll(
|
||||
PhoneMultiFactorGenerator.getAssertion(
|
||||
credential,
|
||||
),
|
||||
);
|
||||
} on FirebaseAuthException catch (e) {
|
||||
print(e.message);
|
||||
}
|
||||
}
|
||||
},
|
||||
codeAutoRetrievalTimeout: print,
|
||||
);
|
||||
},
|
||||
child: const Text('Verify Number For MFA'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
final totp =
|
||||
(await user.multiFactor.getEnrolledFactors())
|
||||
.firstWhereOrNull(
|
||||
(element) => element.factorId == 'totp',
|
||||
);
|
||||
if (totp != null) {
|
||||
await user.multiFactor.unenroll(
|
||||
factorUid:
|
||||
(await user.multiFactor.getEnrolledFactors())
|
||||
.firstWhere(
|
||||
(element) => element.factorId == 'totp',
|
||||
)
|
||||
.uid,
|
||||
);
|
||||
}
|
||||
final session = await user.multiFactor.getSession();
|
||||
final totpSecret =
|
||||
await TotpMultiFactorGenerator.generateSecret(
|
||||
session,
|
||||
);
|
||||
print(totpSecret);
|
||||
final code =
|
||||
await getTotpFromUser(context, totpSecret);
|
||||
print('code: $code');
|
||||
if (code == null) {
|
||||
return;
|
||||
}
|
||||
await user.multiFactor.enroll(
|
||||
await TotpMultiFactorGenerator
|
||||
.getAssertionForEnrollment(
|
||||
totpSecret,
|
||||
code,
|
||||
),
|
||||
displayName: 'TOTP',
|
||||
);
|
||||
},
|
||||
child: const Text('Enroll TOTP'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
final enrolledFactors =
|
||||
await user.multiFactor.getEnrolledFactors();
|
||||
|
||||
await user.multiFactor.unenroll(
|
||||
factorUid: enrolledFactors.first.uid,
|
||||
);
|
||||
// Show snackbar
|
||||
ScaffoldSnackbar.of(context).show('MFA unenrolled');
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
},
|
||||
child: const Text('Unenroll MFA'),
|
||||
),
|
||||
const Divider(),
|
||||
TextButton(
|
||||
onPressed: _signOut,
|
||||
child: const Text('Sign out'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned.directional(
|
||||
textDirection: Directionality.of(context),
|
||||
end: 40,
|
||||
top: 40,
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: !showSaveButton
|
||||
? SizedBox(key: UniqueKey())
|
||||
: TextButton(
|
||||
onPressed: isLoading ? null : updateDisplayName,
|
||||
child: const Text('Save changes'),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<String?> getPhotoURLFromUser() async {
|
||||
String? photoURL;
|
||||
|
||||
// Update the UI - wait for the user to enter the SMS code
|
||||
await showDialog<String>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text('New image Url:'),
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('Update'),
|
||||
),
|
||||
OutlinedButton(
|
||||
onPressed: () {
|
||||
photoURL = null;
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
],
|
||||
content: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: TextField(
|
||||
onChanged: (value) {
|
||||
photoURL = value;
|
||||
},
|
||||
textAlign: TextAlign.center,
|
||||
autofocus: true,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return photoURL;
|
||||
}
|
||||
|
||||
/// Example code for sign out.
|
||||
Future<void> _signOut() async {
|
||||
await auth.signOut();
|
||||
await GoogleSignIn().signOut();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "ephemeral/Flutter-Generated.xcconfig"
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "ephemeral/Flutter-Generated.xcconfig"
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
platform :osx, '10.15'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
project 'Runner', {
|
||||
'Debug' => :debug,
|
||||
'Profile' => :release,
|
||||
'Release' => :release,
|
||||
}
|
||||
|
||||
def flutter_root
|
||||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
|
||||
unless File.exist?(generated_xcode_build_settings_path)
|
||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
|
||||
end
|
||||
|
||||
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||
return matches[1].strip if matches
|
||||
end
|
||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
|
||||
end
|
||||
|
||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||
|
||||
flutter_macos_podfile_setup
|
||||
|
||||
target 'Runner' do
|
||||
use_frameworks!
|
||||
use_modular_headers!
|
||||
|
||||
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
flutter_additional_macos_build_settings(target)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,718 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXAggregateTarget section */
|
||||
33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
|
||||
isa = PBXAggregateTarget;
|
||||
buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
|
||||
buildPhases = (
|
||||
33CC111E2044C6BF0003C045 /* ShellScript */,
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Flutter Assemble";
|
||||
productName = FLX;
|
||||
};
|
||||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
25A01FB0278D938300D1E790 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 25A01FAF278D938300D1E790 /* GoogleService-Info.plist */; };
|
||||
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
|
||||
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
|
||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
|
||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
|
||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
|
||||
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
|
||||
B6036D992F5B77F0D48D7883 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1026236A547BC5196614E954 /* Pods_Runner.framework */; };
|
||||
C0151CEAF69E3751D6A8FA78 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2F30ED8EF0A1349EA81AEE1A /* GoogleService-Info.plist */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 33CC111A2044C6BA0003C045;
|
||||
remoteInfo = FLX;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
33CC110E2044A8840003C045 /* Bundle Framework */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
);
|
||||
name = "Bundle Framework";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0B4CF9B1CA3F6E07FE2F953C /* 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>"; };
|
||||
1026236A547BC5196614E954 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
1E5E064344044E24673A33BD /* 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>"; };
|
||||
25A01FAF278D938300D1E790 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
2F30ED8EF0A1349EA81AEE1A /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
|
||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
|
||||
33CC10ED2044A3C60003C045 /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
|
||||
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = "<group>"; };
|
||||
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = "<group>"; };
|
||||
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = "<group>"; };
|
||||
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = "<group>"; };
|
||||
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = "<group>"; };
|
||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
|
||||
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
|
||||
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
|
||||
3D7BD4B06D0869EA1407E048 /* 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>"; };
|
||||
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
33CC10EA2044A3C60003C045 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
|
||||
B6036D992F5B77F0D48D7883 /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
286E7513A68DD39907D77423 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3D7BD4B06D0869EA1407E048 /* Pods-Runner.debug.xcconfig */,
|
||||
1E5E064344044E24673A33BD /* Pods-Runner.release.xcconfig */,
|
||||
0B4CF9B1CA3F6E07FE2F953C /* Pods-Runner.profile.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33BA886A226E78AF003329D5 /* Configs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33E5194F232828860026EE4D /* AppInfo.xcconfig */,
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||
333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
|
||||
);
|
||||
path = Configs;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CC10E42044A3C60003C045 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33FAB671232836740065AC1E /* Runner */,
|
||||
33CEB47122A05771004F2AC0 /* Flutter */,
|
||||
33CC10EE2044A3C60003C045 /* Products */,
|
||||
D73912EC22F37F3D000D13A0 /* Frameworks */,
|
||||
286E7513A68DD39907D77423 /* Pods */,
|
||||
2F30ED8EF0A1349EA81AEE1A /* GoogleService-Info.plist */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CC10EE2044A3C60003C045 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33CC10ED2044A3C60003C045 /* example.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CC11242044D66E0003C045 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
33CC10F22044A3C60003C045 /* Assets.xcassets */,
|
||||
33CC10F42044A3C60003C045 /* MainMenu.xib */,
|
||||
33CC10F72044A3C60003C045 /* Info.plist */,
|
||||
);
|
||||
name = Resources;
|
||||
path = ..;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33CEB47122A05771004F2AC0 /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */,
|
||||
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
|
||||
33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
|
||||
33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
|
||||
33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
|
||||
);
|
||||
path = Flutter;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
33FAB671232836740065AC1E /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
25A01FAF278D938300D1E790 /* GoogleService-Info.plist */,
|
||||
33CC10F02044A3C60003C045 /* AppDelegate.swift */,
|
||||
33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
|
||||
33E51913231747F40026EE4D /* DebugProfile.entitlements */,
|
||||
33E51914231749380026EE4D /* Release.entitlements */,
|
||||
33CC11242044D66E0003C045 /* Resources */,
|
||||
33BA886A226E78AF003329D5 /* Configs */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1026236A547BC5196614E954 /* Pods_Runner.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
33CC10EC2044A3C60003C045 /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
9C4FABD4FD7B8936CFFEAF31 /* [CP] Check Pods Manifest.lock */,
|
||||
33CC10E92044A3C60003C045 /* Sources */,
|
||||
33CC10EA2044A3C60003C045 /* Frameworks */,
|
||||
33CC10EB2044A3C60003C045 /* Resources */,
|
||||
33CC110E2044A8840003C045 /* Bundle Framework */,
|
||||
3399D490228B24CF009A79C7 /* ShellScript */,
|
||||
E033F9E34514FF7F419D8FF5 /* [CP] Embed Pods Frameworks */,
|
||||
91D69FDB92A2BAB6493D7E50 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
33CC11202044C79F0003C045 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Runner;
|
||||
packageProductDependencies = (
|
||||
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
|
||||
);
|
||||
productName = Runner;
|
||||
productReference = 33CC10ED2044A3C60003C045 /* example.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
33CC10E52044A3C60003C045 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0920;
|
||||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "The Flutter Authors";
|
||||
TargetAttributes = {
|
||||
33CC10EC2044A3C60003C045 = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
LastSwiftMigration = 1100;
|
||||
ProvisioningStyle = Automatic;
|
||||
SystemCapabilities = {
|
||||
com.apple.Sandbox = {
|
||||
enabled = 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
33CC111A2044C6BA0003C045 = {
|
||||
CreatedOnToolsVersion = 9.2;
|
||||
ProvisioningStyle = Manual;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
|
||||
compatibilityVersion = "Xcode 8.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 33CC10E42044A3C60003C045;
|
||||
packageReferences = (
|
||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */,
|
||||
);
|
||||
productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
33CC10EC2044A3C60003C045 /* Runner */,
|
||||
33CC111A2044C6BA0003C045 /* Flutter Assemble */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
33CC10EB2044A3C60003C045 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
|
||||
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
|
||||
25A01FB0278D938300D1E790 /* GoogleService-Info.plist in Resources */,
|
||||
C0151CEAF69E3751D6A8FA78 /* GoogleService-Info.plist in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3399D490228B24CF009A79C7 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
|
||||
};
|
||||
33CC111E2044C6BF0003C045 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
Flutter/ephemeral/FlutterInputs.xcfilelist,
|
||||
);
|
||||
inputPaths = (
|
||||
Flutter/ephemeral/tripwire,
|
||||
);
|
||||
outputFileListPaths = (
|
||||
Flutter/ephemeral/FlutterOutputs.xcfilelist,
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh\ntouch Flutter/ephemeral/tripwire\n";
|
||||
};
|
||||
91D69FDB92A2BAB6493D7E50 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/google_sign_in_ios/google_sign_in_ios_privacy.bundle",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/google_sign_in_ios_privacy.bundle",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9C4FABD4FD7B8936CFFEAF31 /* [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;
|
||||
};
|
||||
E033F9E34514FF7F419D8FF5 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
|
||||
"${BUILT_PRODUCTS_DIR}/AppAuth/AppAuth.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/GTMAppAuth/GTMAppAuth.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/GoogleSignIn/GoogleSignIn.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/facebook_auth_desktop/facebook_auth_desktop.framework",
|
||||
"${BUILT_PRODUCTS_DIR}/flutter_secure_storage_macos/flutter_secure_storage_macos.framework",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AppAuth.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMAppAuth.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleSignIn.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/facebook_auth_desktop.framework",
|
||||
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_secure_storage_macos.framework",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
33CC10E92044A3C60003C045 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
|
||||
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
|
||||
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
|
||||
targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
33CC10F52044A3C60003C045 /* Base */,
|
||||
);
|
||||
name = MainMenu.xib;
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
338D0CE9231458BD00FA5F75 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
338D0CEA231458BD00FA5F75 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = YYX2P3XVJ7;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter/ephemeral",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firebase.auth.example;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
338D0CEB231458BD00FA5F75 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
33CC10F92044A3C60003C045 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
33CC10FA2044A3C60003C045 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
33CC10FC2044A3C60003C045 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = YYX2P3XVJ7;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter/ephemeral",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firebase.auth.example;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
33CC10FD2044A3C60003C045 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEVELOPMENT_TEAM = YYX2P3XVJ7;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Flutter/ephemeral",
|
||||
);
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.firebase.auth.example;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
33CC111C2044C6BA0003C045 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
33CC111D2044C6BA0003C045 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
33CC10F92044A3C60003C045 /* Debug */,
|
||||
33CC10FA2044A3C60003C045 /* Release */,
|
||||
338D0CE9231458BD00FA5F75 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
33CC10FC2044A3C60003C045 /* Debug */,
|
||||
33CC10FD2044A3C60003C045 /* Release */,
|
||||
338D0CEA231458BD00FA5F75 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
33CC111C2044C6BA0003C045 /* Debug */,
|
||||
33CC111D2044C6BA0003C045 /* Release */,
|
||||
338D0CEB231458BD00FA5F75 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCLocalSwiftPackageReference section */
|
||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = {
|
||||
isa = XCLocalSwiftPackageReference;
|
||||
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
|
||||
};
|
||||
/* End XCLocalSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = FlutterGeneratedPluginSwiftPackage;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 33CC10E52044A3C60003C045 /* Project object */;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:/Users/stuartmorgan/src/embedder-opensource/flutter-desktop-embedding/example/macos/Runner.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,120 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<PreActions>
|
||||
<ExecutionAction
|
||||
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
|
||||
<ActionContent
|
||||
title = "Run Prepare Flutter Framework Script"
|
||||
scriptText = ""$FLUTTER_ROOT"/packages/flutter_tools/bin/macos_assemble.sh prepare ">
|
||||
<EnvironmentBuildable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "example.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</EnvironmentBuildable>
|
||||
</ActionContent>
|
||||
</ExecutionAction>
|
||||
</PreActions>
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "example.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">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "00380F9121DF178D00097171"
|
||||
BuildableName = "RunnerUITests.xctest"
|
||||
BlueprintName = "RunnerUITests"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "example.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</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 = "example.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||
BuildableName = "example.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
|
|
@ -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>
|
||||