capacitor-native-google-one-tap-signin 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CapacitorNativeGoogleOneTapSignin.podspec +2 -1
  2. package/README.md +9 -4
  3. package/android/.gradle/7.3.3/checksums/checksums.lock +0 -0
  4. package/android/.gradle/7.3.3/dependencies-accessors/dependencies-accessors.lock +0 -0
  5. package/android/.gradle/7.3.3/executionHistory/executionHistory.bin +0 -0
  6. package/android/.gradle/7.3.3/executionHistory/executionHistory.lock +0 -0
  7. package/android/.gradle/7.3.3/fileHashes/fileHashes.bin +0 -0
  8. package/android/.gradle/7.3.3/fileHashes/fileHashes.lock +0 -0
  9. package/android/.gradle/7.3.3/fileHashes/resourceHashesCache.bin +0 -0
  10. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  11. package/android/.gradle/buildOutputCleanup/cache.properties +1 -1
  12. package/android/.gradle/buildOutputCleanup/outputFiles.bin +0 -0
  13. package/android/.idea/workspace.xml +89 -0
  14. package/android/src/main/java/com/proventask/capacitor/GoogleOneTapAuth/GoogleOneTapAuth.java +113 -49
  15. package/dist/esm/definitions.d.ts +86 -16
  16. package/dist/esm/web.d.ts +19 -16
  17. package/dist/esm/web.js +116 -85
  18. package/dist/esm/web.js.map +1 -1
  19. package/package.json +8 -2
  20. package/android/.gradle/4.10.1/fileChanges/last-build.bin +0 -0
  21. package/android/.gradle/4.10.1/fileHashes/fileHashes.bin +0 -0
  22. package/android/.gradle/4.10.1/fileHashes/fileHashes.lock +0 -0
  23. package/android/.gradle/4.10.1/gc.properties +0 -0
  24. package/android/.gradle/7.3.3/checksums/md5-checksums.bin +0 -0
  25. package/android/.gradle/7.3.3/checksums/sha1-checksums.bin +0 -0
  26. package/android/.gradle/file-system.probe +0 -0
  27. package/android/.idea/compiler.xml +0 -6
  28. package/android/.idea/gradle.xml +0 -19
  29. package/android/.idea/jarRepositories.xml +0 -30
  30. package/android/.idea/misc.xml +0 -10
  31. package/android/.idea/vcs.xml +0 -6
  32. package/android/local.properties +0 -8
@@ -11,5 +11,6 @@
11
11
  s.ios.deployment_target = '12.0'
12
12
  s.dependency 'Capacitor'
13
13
  s.dependency 'GoogleSignIn', '~> 6.2.4'
14
- s.static_framework = true
14
+ s.static_framework = true,
15
+ s.swift_version = '5.1'
15
16
  end
package/README.md CHANGED
@@ -1,8 +1,11 @@
1
1
  # Capacitor Native Google One Tap Signin plugin
2
2
 
3
- Wraps the native android One Tap sign-in api for ionic capacitor apps.
3
+ Wraps the native android One Tap api for ionic capacitor apps. One Tap Sign In is part of Sign in with Google and offers features as automatic sign-in on return visits.
4
+
5
+ <img src="screenshots/one-tap-sign-in-demo-initial-sign-in.jpg" alt="One tap signin screenshot initial sign-in" width=250/>
6
+ <img src="screenshots/one-tap-sign-in-demo-sign-back-in.jpg" alt="One tap signin screenshot sign back in" width=250/>
7
+ <img src="screenshots/one-tap-sign-in-demo-without-filter-by-authorized-acounts.jpg" alt="One tap signin screenshot without filter by authorized accounts" width=250/>
4
8
 
5
- <img src="screenshots/one-tap-sign-in-demo.jpg" alt="One tap signin screenshot" width=300/>
6
9
 
7
10
  Currently the idToken, id (e-mail), displayName, givenName, familyName, profilePictureUri are returned. You may check the idToken contents on https://jwt.io/.
8
11
 
@@ -17,10 +20,12 @@ See the `demo` folder.
17
20
  # Setup
18
21
  You need to provide the plug-in a client ID of type "Web application". However you will also need to create a client ID of type "Android" as stated in the [One Tap Get started docu](https://developers.google.cn/identity/one-tap/android/get-started) in the [Google Cloud Console](https://console.cloud.google.com/apis/dashboard).
19
22
 
20
- To test it using an emulator, you need to create an emulator with android play services. See [my stackoverflow answer](https://stackoverflow.com/questions/71325279/missing-featurename-auth-api-credentials-begin-sign-in-version-6/75285717#75285717).
23
+ To test it using an emulator, you need to create an emulator with android play services and API version 29 or higher. See [my stackoverflow answer](https://stackoverflow.com/questions/71325279/missing-featurename-auth-api-credentials-begin-sign-in-version-6/75285717#75285717).
21
24
 
22
- ## Contributions
25
+ # Design decisions
26
+ Promises will not be rejected for anticipated unsuccessful control flow. For example, if the one tap auto-login does not succeed with the reason `opt_out_or_no_session` then this is not exceptional but expected in many cases. Rejecting the promise would mean the caller would have to catch an exception when calling `await xy` and then run follow-up code in the catch block. Instead of rejecting promises the resolved promise contains a `isSuccess` property.
23
27
 
28
+ ## Contributions
24
29
  Welcome
25
30
 
26
31
  ## Install
@@ -1,2 +1,2 @@
1
- #Fri Jan 27 18:42:37 CET 2023
1
+ #Wed Feb 01 10:00:31 CET 2023
2
2
  gradle.version=7.3.3
@@ -0,0 +1,89 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="AnalysisUIOptions">
4
+ <option name="ANALYZE_TEST_SOURCES" value="false" />
5
+ <option name="SCOPE_TYPE" value="3" />
6
+ </component>
7
+ <component name="AndroidLayouts">
8
+ <shared>
9
+ <config />
10
+ </shared>
11
+ </component>
12
+ <component name="AutoImportSettings">
13
+ <option name="autoReloadType" value="NONE" />
14
+ </component>
15
+ <component name="ChangeListManager">
16
+ <list default="true" id="0b55ef2b-cc9f-4db3-a856-ce6b62a86d75" name="Changes" comment="">
17
+ <change beforePath="$PROJECT_DIR$/../README.md" beforeDir="false" afterPath="$PROJECT_DIR$/../README.md" afterDir="false" />
18
+ </list>
19
+ <option name="SHOW_DIALOG" value="false" />
20
+ <option name="HIGHLIGHT_CONFLICTS" value="true" />
21
+ <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
22
+ <option name="LAST_RESOLUTION" value="IGNORE" />
23
+ </component>
24
+ <component name="ExternalProjectsData">
25
+ <projectState path="$PROJECT_DIR$">
26
+ <ProjectState />
27
+ </projectState>
28
+ </component>
29
+ <component name="Git.Settings">
30
+ <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
31
+ </component>
32
+ <component name="MarkdownSettingsMigration">
33
+ <option name="stateVersion" value="1" />
34
+ </component>
35
+ <component name="ProjectId" id="2Kv3cryAzMEsXS9WG3m2lrbwue2" />
36
+ <component name="ProjectLevelVcsManager" settingsEditedManually="true" />
37
+ <component name="ProjectViewState">
38
+ <option name="hideEmptyMiddlePackages" value="true" />
39
+ <option name="showLibraryContents" value="true" />
40
+ </component>
41
+ <component name="PropertiesComponent">{
42
+ &quot;keyToString&quot;: {
43
+ &quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
44
+ &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
45
+ &quot;RunOnceActivity.cidr.known.project.marker&quot;: &quot;true&quot;,
46
+ &quot;cidr.known.project.marker&quot;: &quot;true&quot;,
47
+ &quot;run.code.analysis.last.selected.profile&quot;: &quot;pProject Default&quot;,
48
+ &quot;settings.editor.selected.configurable&quot;: &quot;preferences.keymap&quot;
49
+ }
50
+ }</component>
51
+ <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
52
+ <component name="TaskManager">
53
+ <task active="true" id="Default" summary="Default task">
54
+ <changelist id="0b55ef2b-cc9f-4db3-a856-ce6b62a86d75" name="Changes" comment="" />
55
+ <created>1674841311917</created>
56
+ <option name="number" value="Default" />
57
+ <option name="presentableId" value="Default" />
58
+ <updated>1674841311917</updated>
59
+ </task>
60
+ <servers />
61
+ </component>
62
+ <component name="Vcs.Log.Tabs.Properties">
63
+ <option name="TAB_STATES">
64
+ <map>
65
+ <entry key="MAIN">
66
+ <value>
67
+ <State />
68
+ </value>
69
+ </entry>
70
+ </map>
71
+ </option>
72
+ </component>
73
+ <component name="XDebuggerManager">
74
+ <breakpoint-manager>
75
+ <breakpoints>
76
+ <line-breakpoint enabled="true" type="java-line">
77
+ <url>file://$PROJECT_DIR$/src/main/java/com/proventask/capacitor/GoogleOneTapAuth/GoogleOneTapAuth.java</url>
78
+ <line>26</line>
79
+ <option name="timeStamp" value="1" />
80
+ </line-breakpoint>
81
+ <line-breakpoint enabled="true" type="java-line">
82
+ <url>file://$PROJECT_DIR$/src/main/java/com/proventask/capacitor/GoogleOneTapAuth/GoogleOneTapAuth.java</url>
83
+ <line>36</line>
84
+ <option name="timeStamp" value="2" />
85
+ </line-breakpoint>
86
+ </breakpoints>
87
+ </breakpoint-manager>
88
+ </component>
89
+ </project>
@@ -15,7 +15,6 @@ import com.getcapacitor.Plugin;
15
15
  import com.getcapacitor.PluginCall;
16
16
  import com.getcapacitor.PluginMethod;
17
17
  import com.getcapacitor.annotation.CapacitorPlugin;
18
-
19
18
  import com.google.android.gms.auth.api.identity.BeginSignInRequest;
20
19
  import com.google.android.gms.auth.api.identity.Identity;
21
20
  import com.google.android.gms.auth.api.identity.SignInClient;
@@ -23,23 +22,26 @@ import com.google.android.gms.common.ConnectionResult;
23
22
  import com.google.android.gms.common.GoogleApiAvailability;
24
23
  import com.google.android.gms.common.api.ApiException;
25
24
 
25
+ import java.util.Base64;
26
+ import java.util.concurrent.CompletableFuture;
27
+ import java.util.concurrent.ExecutionException;
28
+ import java.util.concurrent.Future;
29
+
26
30
  @CapacitorPlugin()
27
31
  public class GoogleOneTapAuth extends Plugin {
28
32
  private static final String TAG = "GoogleOneTapAuth Plugin";
29
- private String androidClientId;
33
+ private String clientId;
30
34
  private SignInClient oneTapClient;
31
- private PluginCall currentPluginCall = null;
32
35
  private ActivityResultLauncher<IntentSenderRequest> googleOneTapSignInActivityResultHandlerIntentSenderRequest;
33
-
36
+ private CompletableFuture<JSObject> signInFuture;
34
37
 
35
38
  @Override
36
39
  public void load() {
37
- androidClientId = getConfig().getString("androidClientId");
40
+ clientId = getConfig().getString("clientId");
38
41
 
39
- if (androidClientId == null || androidClientId.endsWith("apps.googleusercontent.com") == false) {
40
- throw new RuntimeException("androidClientId must end with 'apps.googleusercontent.com' but is: " + androidClientId + ". Check capacitor.config.ts.");
42
+ if (clientId == null || clientId.endsWith("apps.googleusercontent.com") == false) {
43
+ throw new RuntimeException("clientId must end with 'apps.googleusercontent.com' but is: " + clientId + ". Check capacitor.config.ts.");
41
44
  }
42
-
43
45
  oneTapClient = Identity.getSignInClient(this.getActivity());
44
46
  RegisterSignInResultHandler();
45
47
  }
@@ -49,41 +51,72 @@ public class GoogleOneTapAuth extends Plugin {
49
51
  new ActivityResultContracts.StartIntentSenderForResult(),
50
52
  result -> {
51
53
  var resultCode = result.getResultCode();
52
- var resultCodeString = ActivityResult.resultCodeToString(resultCode);
53
- Intent data = result.getData();
54
-
55
- var pluginResult = new JSObject();
56
- pluginResult.put("resultCodeString", resultCodeString);
57
54
 
58
55
  if (resultCode == Activity.RESULT_OK) {
59
56
  try {
57
+ Intent data = result.getData();
60
58
  var credential = oneTapClient.getSignInCredentialFromIntent(data);
61
- pluginResult.put("id", credential.getId());
62
- pluginResult.put("idToken", credential.getGoogleIdToken());
63
- pluginResult.put("displayName", credential.getDisplayName());
64
- pluginResult.put("givenName", credential.getGivenName());
65
- pluginResult.put("familyName", credential.getFamilyName());
66
- pluginResult.put("profilePictureUri", credential.getProfilePictureUri() == null ? null : credential.getProfilePictureUri().toString());
67
- currentPluginCall.resolve(pluginResult);
59
+ var email = credential.getId();
60
+ signInFuture.complete(createSuccessResponse(credential.getGoogleIdToken(), email));
68
61
  } catch (ApiException e) {
69
- currentPluginCall.reject(e.toString(), pluginResult);
62
+ signInFuture.complete(createErrorResponse(e.toString()));
70
63
  }
71
64
  } else {
72
- currentPluginCall.reject(resultCodeString, pluginResult);
65
+ var resultCodeString = ActivityResult.resultCodeToString(resultCode);
66
+ signInFuture.complete(createErrorResponse(resultCodeString));
73
67
  }
74
68
  });
75
69
  }
76
70
 
77
71
  @PluginMethod()
78
- public void signIn(PluginCall call) {
79
- currentPluginCall = call;
80
- beginSignIn(true);
72
+ public void initialize(PluginCall call) {
73
+ // Currently no code to run here.
74
+ call.resolve();
75
+ }
76
+
77
+ @PluginMethod()
78
+ public void tryAutoSignIn(PluginCall call) {
79
+ try {
80
+ var signInResult = beginSignIn(true).get();
81
+ call.resolve(signInResult);
82
+ } catch (ExecutionException e) {
83
+ call.reject(e.toString());
84
+ } catch (InterruptedException e) {
85
+ call.reject(e.toString());
86
+ }
81
87
  }
82
88
 
83
- // This method is called first with tryAutoLogin=true and if not successful then with tryAutoLogin=false.
84
- private void beginSignIn(boolean tryAutoLogin) {
89
+ @PluginMethod()
90
+ public void trySignInWithPrompt(PluginCall call) {
91
+ try {
92
+ var signInResult = beginSignIn(false).get();
93
+ call.resolve(signInResult);
94
+ } catch (ExecutionException e) {
95
+ call.reject(e.toString());
96
+ } catch (InterruptedException e) {
97
+ call.reject(e.toString());
98
+ }
99
+ }
100
+
101
+ @PluginMethod()
102
+ public void tryAutoSignInThenTrySignInWithPrompt(PluginCall call) {
103
+ try {
104
+ var signInResult = beginSignIn(true).get();
105
+ if (!signInResult.getBool("isSuccess")) {
106
+ signInResult = beginSignIn(false).get();
107
+ }
108
+ call.resolve(signInResult);
109
+ } catch (ExecutionException e) {
110
+ call.reject(e.toString());
111
+ } catch (InterruptedException e) {
112
+ call.reject(e.toString());
113
+ }
114
+ }
115
+
116
+ private Future<JSObject> beginSignIn(boolean filterByAuthorizedAccounts) {
85
117
  var context = this.getContext();
86
- var beginSignInRequest = createBeginSignInRequest(tryAutoLogin);
118
+ var beginSignInRequest = createBeginSignInRequest(filterByAuthorizedAccounts);
119
+ signInFuture = new CompletableFuture<>();
87
120
 
88
121
  oneTapClient.beginSignIn(beginSignInRequest)
89
122
  .addOnCompleteListener(task -> {
@@ -93,42 +126,70 @@ public class GoogleOneTapAuth extends Plugin {
93
126
  var intentSenderRequest = new IntentSenderRequest.Builder(intentSender).build();
94
127
  googleOneTapSignInActivityResultHandlerIntentSenderRequest.launch(intentSenderRequest);
95
128
  } else {
96
- if (tryAutoLogin) {
97
- beginSignIn(false);
129
+ if (filterByAuthorizedAccounts) {
130
+ Log.i(TAG, "beginSignIn with FilterByAuthorizedAccounts=true failed", task.getException());
98
131
  } else {
99
- Log.e(TAG, "beginSignIn failed", task.getException());
100
- var errorMessage = task.getException().toString();
101
-
102
- if (!isGooglePlayServicesAvailable(context)) {
103
- errorMessage += "\nGooglePlayService is not installed or must be updated.";
104
- }
105
- if (errorMessage.contains("Missing Feature{name=auth_api_credentials_begin_sign_in")) {
106
- errorMessage += "\nGooglePlay is not installed or must be logged in to setup.";
107
- }
108
- if (errorMessage.contains("ApiException: 8")) {
109
- errorMessage += "\nOne reason for the exception is when the device has no internet.";
110
- }
111
- currentPluginCall.reject(errorMessage);
132
+ Log.e(TAG, "beginSignIn with FilterByAuthorizedAccounts=false failed", task.getException());
133
+ }
134
+ var errorMessage = task.getException().toString();
135
+
136
+ if (!isGooglePlayServicesAvailable(context)) {
137
+ errorMessage += "\nGooglePlayService is not installed or must be updated.";
138
+ }
139
+ if (errorMessage.contains("Missing Feature{name=auth_api_credentials_begin_sign_in")) {
140
+ errorMessage += "\nGooglePlay is not installed or must be logged in to setup.";
141
+ }
142
+ if (errorMessage.contains("ApiException: 8")) {
143
+ errorMessage += "\nOne reason for the exception is when the device has no internet.";
112
144
  }
145
+ // Other errors:
146
+ // com.google.android.gms.common.api.ApiException: 10: Caller not whitelisted to call this API.
147
+ // --> Try if restarting the phone fixes the problem.
148
+ // --> Test to sign in several times to ensure it works repeatedly.
149
+ signInFuture.complete(createErrorResponse(errorMessage));
113
150
  }
114
151
  });
152
+ return signInFuture;
115
153
  }
116
154
 
117
- private BeginSignInRequest createBeginSignInRequest(boolean tryAutoLogin) {
155
+ private BeginSignInRequest createBeginSignInRequest(boolean filterByAuthorizedAccounts) {
118
156
  return BeginSignInRequest.builder()
119
157
  .setGoogleIdTokenRequestOptions(BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
120
158
  .setSupported(true)
121
159
  // A OAuth client ID with application type "Web application".
122
- .setServerClientId(androidClientId)
160
+ .setServerClientId(clientId)
123
161
  // If true, only the Google accounts that the user has authorized before will show up in the credential list. This can
124
162
  // help prevent a new account being created when the user has an existing account registered with the application.
125
- .setFilterByAuthorizedAccounts(tryAutoLogin)
163
+ .setFilterByAuthorizedAccounts(filterByAuthorizedAccounts)
126
164
  .build())
127
165
  // For users who opt-in, Auto Select allows a credential to be selected automatically without waiting for a user action (such as tapping on the "continue" button).
128
- .setAutoSelectEnabled(tryAutoLogin)
166
+ .setAutoSelectEnabled(true)
129
167
  .build();
130
168
  }
131
169
 
170
+ private JSObject createErrorResponse(String noSuccessAdditionalInfo) {
171
+ var result = new JSObject();
172
+ result.put("isSuccess", false);
173
+ result.put("noSuccessAdditionalInfo", noSuccessAdditionalInfo);
174
+ return result;
175
+ }
176
+
177
+ private JSObject createSuccessResponse(String idToken, String email) {
178
+ var result = new JSObject();
179
+ result.put("isSuccess", true);
180
+ result.put("idToken", idToken);
181
+ result.put("email", email);
182
+ result.put("decodedIdToken", decodeJwtBody(idToken));
183
+ return result;
184
+ }
185
+
186
+ private String decodeJwtBody(String jwtToken) {
187
+ var decoder = Base64.getUrlDecoder();
188
+ var parts = jwtToken.split("\\.");
189
+ var payloadJson = new String(decoder.decode(parts[1]));
190
+ return payloadJson;
191
+ }
192
+
132
193
  private boolean isGooglePlayServicesAvailable(Context context) {
133
194
  var googleApiAvailability = GoogleApiAvailability.getInstance();
134
195
  int resultCode = googleApiAvailability.isGooglePlayServicesAvailable(context);
@@ -139,12 +200,15 @@ public class GoogleOneTapAuth extends Plugin {
139
200
  public void signOut(final PluginCall call) {
140
201
  oneTapClient.signOut()
141
202
  .addOnCompleteListener(task -> {
203
+ var signOutResult = new JSObject();
142
204
  if (task.isSuccessful()) {
143
- call.resolve(null);
205
+ signOutResult.put("isSuccess", true);
144
206
  } else {
145
207
  Log.e(TAG, "signOut failed", task.getException());
146
- call.reject(task.getException().toString());
208
+ signOutResult.put("isSuccess", false);
209
+ signOutResult.put("error", task.getException().toString());
147
210
  }
211
+ call.resolve(signOutResult);
148
212
  });
149
213
  }
150
214
  }
@@ -3,27 +3,97 @@ declare module '@capacitor/cli' {
3
3
  GoogleOneTapAuth: GoogleOneTapAuthPluginOptions;
4
4
  }
5
5
  }
6
- export interface User {
7
- id: string;
8
- idToken: string;
9
- displayName: string;
10
- givenName: string;
11
- familyName: string;
12
- profilePictureUri: string;
13
- }
6
+ /**
7
+ * Options that can be defined in capacitor.config.ts.
8
+ */
14
9
  export interface GoogleOneTapAuthPluginOptions {
15
10
  /**
16
- * Web application client ID key for android platform
11
+ * Your client ID of type Web application. Can also be set in capacitor.config.ts.
12
+ */
13
+ clientId?: string;
14
+ }
15
+ export interface SignInOptions extends GoogleOneTapAuthPluginOptions {
16
+ /**
17
+ * A random string for ID tokens.
17
18
  */
18
- androidClientId?: string;
19
+ nonce?: string;
19
20
  /**
20
- * Web application client ID key for web platform
21
+ * Additional options for the web platform.
21
22
  */
22
- webClientId?: string;
23
+ webOptions?: SignInWebOptions;
23
24
  }
24
- export interface GoogleOneTapAuthPlugin {
25
- signIn(): Promise<User>;
26
- signOut(): Promise<any>;
25
+ export interface SignInWebOptions {
26
+ /**
27
+ * Enables upgraded One Tap UX on ITP browsers. The default value is false.
28
+ */
29
+ itpSupport?: boolean;
30
+ /**
31
+ * The Sign In With Google button UX flow. The default value is 'popup'.
32
+ */
33
+ uxMode?: 'popup' | 'redirect';
34
+ }
35
+ export interface SignInResult {
36
+ isSuccess: boolean;
37
+ /**
38
+ * A reason code as 'opt_out_or_no_session'.
39
+ * Currently not available for android, only if the js library is used.
40
+ * For possible values see google.PromptMomentNotification.
41
+ */
42
+ noSuccessReasonCode?: string;
43
+ /**
44
+ * A error message.
45
+ * Set in case of error if the native android code is used.
46
+ */
47
+ noSuccessAdditionalInfo?: string;
48
+ /**
49
+ * How the credential was retrieved.
50
+ * Currently not available for android, only if the js library is used.
51
+ * For possible values see google.PromptMomentNotification.
52
+ */
53
+ selectBy?: 'auto' | 'user' | 'user_1tap' | 'user_2tap' | 'btn' | 'btn_confirm' | 'btn_add_session' | 'btn_confirm_add_session';
54
+ /**
55
+ * The JWT token base64 encoded.
56
+ * Will be set if successful.
57
+ */
58
+ idToken?: string;
59
+ /**
60
+ * The email address.
61
+ */
62
+ email?: string;
63
+ /**
64
+ * The decoded JWT token.
65
+ * Will be set if successful.
66
+ * The signature is not verified when decoding the token.
67
+ */
68
+ decodedIdToken?: any;
27
69
  }
28
- export interface WebInitOptions extends Pick<GoogleOneTapAuthPluginOptions, 'webClientId'> {
70
+ export interface SignOutResult {
71
+ isSuccess: boolean;
72
+ error?: string;
73
+ }
74
+ export interface GoogleOneTapAuthPlugin {
75
+ /**
76
+ * For the web platform, starts pre-loading the google one tap JavaScript library. Calling initialize is optional.
77
+ */
78
+ initialize(): Promise<void>;
79
+ /**
80
+ * Tries to auto-sign in the user.
81
+ * If there is no single user session that logged in previously in the app, the sign-in will fail.
82
+ * @param options
83
+ */
84
+ tryAutoSignIn(options: SignInOptions): Promise<SignInResult>;
85
+ /**
86
+ * Tries to shows the one-tab user selection popup.
87
+ * If there is no authorized session in the browser it will fail and the login button must be shown.
88
+ * @param options
89
+ */
90
+ trySignInWithPrompt(options: SignInOptions): Promise<SignInResult>;
91
+ /**
92
+ * Tries to auto-sign in the user and if not possible tries to shows the one-tab user selection.
93
+ * If there is no authorized session in the browser it will fail and the login button must be shown.
94
+ * @param options
95
+ */
96
+ tryAutoSignInThenTrySignInWithPrompt(options: SignInOptions): Promise<SignInResult>;
97
+ signOut(): Promise<SignOutResult>;
98
+ renderButton(parentElementId: string, options: SignInOptions, gsiButtonConfiguration?: google.GsiButtonConfiguration): Promise<SignInResult>;
29
99
  }
package/dist/esm/web.d.ts CHANGED
@@ -1,19 +1,22 @@
1
1
  import { WebPlugin } from '@capacitor/core';
2
- import { GoogleOneTapAuthPlugin, WebInitOptions, User } from './definitions';
2
+ import { SignInResult, SignOutResult, GoogleOneTapAuthPlugin, SignInOptions } from './definitions';
3
3
  export declare class GoogleOneTapAuthWeb extends WebPlugin implements GoogleOneTapAuthPlugin {
4
- gapiLoaded: Promise<void>;
5
- options: WebInitOptions;
6
- constructor();
7
- loadScript(): void;
8
- initialize(_options?: Partial<WebInitOptions>): void;
9
- platformJsLoaded(): void;
10
- signIn(): Promise<User>;
11
- refresh(): Promise<{
12
- accessToken: string;
13
- idToken: string;
14
- refreshToken: string;
15
- }>;
16
- signOut(): Promise<any>;
17
- private addUserChangeListener;
18
- private getUserFrom;
4
+ gsiScriptUrl: string;
5
+ gapiLoadedPromise: Promise<void>;
6
+ resolveGapiLoaded: () => void;
7
+ signInPromise: Promise<SignInResult>;
8
+ resolveSignInPromise: (user: SignInResult) => void;
9
+ authenticatedUserId: string;
10
+ initialize(): Promise<void>;
11
+ private loadScript;
12
+ tryAutoSignIn(options: SignInOptions): Promise<SignInResult>;
13
+ trySignInWithPrompt(options: SignInOptions): Promise<SignInResult>;
14
+ tryAutoSignInThenTrySignInWithPrompt(options: SignInOptions): Promise<SignInResult>;
15
+ renderButton(parentElementId: string, options: SignInOptions, gsiButtonConfiguration?: google.GsiButtonConfiguration): Promise<SignInResult>;
16
+ private doSignIn;
17
+ private createSignInPromise;
18
+ private getMomentReason;
19
+ private oneTapInitialize;
20
+ private handleCredentialResponse;
21
+ signOut(): Promise<SignOutResult>;
19
22
  }
package/dist/esm/web.js CHANGED
@@ -1,105 +1,136 @@
1
1
  import { WebPlugin } from '@capacitor/core';
2
+ import * as scriptjs from 'scriptjs';
3
+ import jwt_decode from 'jwt-decode';
4
+ // See https://developers.google.com/identity/gsi/web/guides/use-one-tap-js-api
2
5
  export class GoogleOneTapAuthWeb extends WebPlugin {
3
6
  constructor() {
4
- super();
7
+ super(...arguments);
8
+ this.gsiScriptUrl = 'https://accounts.google.com/gsi/client';
9
+ this.gapiLoadedPromise = null;
10
+ this.authenticatedUserId = null;
5
11
  }
6
- loadScript() {
7
- if (typeof document === 'undefined') {
8
- return;
9
- }
10
- const scriptId = 'gapi';
11
- const scriptEl = document === null || document === void 0 ? void 0 : document.getElementById(scriptId);
12
- if (scriptEl) {
13
- return;
12
+ initialize() {
13
+ if (this.gapiLoadedPromise == null) {
14
+ this.gapiLoadedPromise = new Promise((resolve) => {
15
+ this.resolveGapiLoaded = resolve;
16
+ });
17
+ this.loadScript();
14
18
  }
15
- const head = document.getElementsByTagName('head')[0];
16
- const script = document.createElement('script');
17
- script.type = 'text/javascript';
18
- script.defer = true;
19
- script.async = true;
20
- script.id = scriptId;
21
- script.onload = this.platformJsLoaded.bind(this);
22
- script.src = 'https://apis.google.com/js/platform.js';
23
- head.appendChild(script);
19
+ return this.gapiLoadedPromise;
24
20
  }
25
- initialize(_options = {
26
- webClientId: '',
27
- }) {
28
- var _a;
29
- if (typeof window === 'undefined') {
30
- return;
31
- }
32
- const metaClientId = (_a = document.getElementsByName('google-signin-client_id')[0]) === null || _a === void 0 ? void 0 : _a.content;
33
- const webClientId = _options.webClientId || metaClientId || '';
34
- if (!webClientId) {
35
- console.warn('GoogleOneTapAuthPlugin - clientId is empty');
21
+ loadScript() {
22
+ scriptjs.get(this.gsiScriptUrl, () => {
23
+ this.resolveGapiLoaded();
24
+ });
25
+ }
26
+ async tryAutoSignIn(options) {
27
+ return await this.doSignIn(options, true);
28
+ }
29
+ async trySignInWithPrompt(options) {
30
+ return await this.doSignIn(options, false);
31
+ }
32
+ async tryAutoSignInThenTrySignInWithPrompt(options) {
33
+ let signInResult = await this.doSignIn(options, true);
34
+ if (!signInResult.isSuccess) {
35
+ signInResult = await this.doSignIn(options, false);
36
36
  }
37
- this.options = {
38
- webClientId,
39
- };
40
- this.gapiLoaded = new Promise((resolve) => {
41
- // HACK: Relying on window object, can't get property in gapi.load callback
42
- window.gapiResolve = resolve;
43
- this.loadScript();
37
+ return signInResult;
38
+ }
39
+ async renderButton(parentElementId, options, gsiButtonConfiguration) {
40
+ const parentElem = document.getElementById(parentElementId);
41
+ assert(() => !!parentElem);
42
+ await this.initialize();
43
+ this.createSignInPromise();
44
+ this.oneTapInitialize(options, false);
45
+ google.accounts.id.renderButton(parentElem, gsiButtonConfiguration || {});
46
+ return this.signInPromise;
47
+ }
48
+ async doSignIn(options, autoSelect) {
49
+ assert(() => !!options.clientId);
50
+ await this.initialize();
51
+ this.createSignInPromise();
52
+ this.oneTapInitialize(options, autoSelect);
53
+ google.accounts.id.prompt((notification) => {
54
+ if (notification.isNotDisplayed()
55
+ || notification.isSkippedMoment()
56
+ || notification.isDismissedMoment()) {
57
+ this.resolveSignInPromise({
58
+ isSuccess: false,
59
+ noSuccessReasonCode: this.getMomentReason(notification)
60
+ });
61
+ this.signInPromise = null;
62
+ }
44
63
  });
45
- this.addUserChangeListener();
64
+ return this.signInPromise;
46
65
  }
47
- platformJsLoaded() {
48
- gapi.load('auth2', () => {
49
- const clientConfig = {
50
- client_id: this.options.webClientId,
51
- plugin_name: 'CapacitorNativeGoogleOneTapSignin',
52
- };
53
- gapi.auth2.init(clientConfig);
54
- window.gapiResolve();
66
+ createSignInPromise() {
67
+ this.signInPromise = new Promise((resolve) => {
68
+ this.resolveSignInPromise = resolve;
55
69
  });
56
70
  }
57
- async signIn() {
58
- return new Promise(async (resolve, reject) => {
59
- try {
60
- await gapi.auth2.getAuthInstance().signIn();
61
- const googleUser = gapi.auth2.getAuthInstance().currentUser.get();
62
- const user = this.getUserFrom(googleUser);
63
- resolve(user);
64
- }
65
- catch (error) {
66
- reject(error);
67
- }
71
+ getMomentReason(notification) {
72
+ if (notification.isNotDisplayed()) {
73
+ return notification.getNotDisplayedReason();
74
+ }
75
+ if (notification.isSkippedMoment()) {
76
+ return notification.getSkippedReason();
77
+ }
78
+ if (notification.isDismissedMoment()) {
79
+ return notification.getDismissedReason();
80
+ }
81
+ return null;
82
+ }
83
+ oneTapInitialize(options, autoSelect) {
84
+ var _a, _b;
85
+ google.accounts.id.initialize({
86
+ client_id: options.clientId,
87
+ callback: this.handleCredentialResponse.bind(this),
88
+ auto_select: autoSelect,
89
+ itp_support: ((_a = options.webOptions) === null || _a === void 0 ? void 0 : _a.itpSupport) || false,
90
+ cancel_on_tap_outside: false,
91
+ ux_mode: ((_b = options.webOptions) === null || _b === void 0 ? void 0 : _b.uxMode) || 'popup',
68
92
  });
69
93
  }
70
- async refresh() {
71
- const authResponse = await gapi.auth2.getAuthInstance().currentUser.get().reloadAuthResponse();
72
- return {
73
- accessToken: authResponse.access_token,
74
- idToken: authResponse.id_token,
75
- refreshToken: '',
94
+ handleCredentialResponse(credentialResponse) {
95
+ const decodedIdToken = jwt_decode(credentialResponse.credential);
96
+ let signInResult = {
97
+ isSuccess: true,
98
+ idToken: credentialResponse.credential,
99
+ email: decodedIdToken.email,
100
+ selectBy: credentialResponse.select_by,
101
+ decodedIdToken: decodedIdToken
76
102
  };
103
+ this.authenticatedUserId = decodedIdToken['sub'];
104
+ // console.log(decodedIdToken);
105
+ this.resolveSignInPromise(signInResult);
106
+ this.signInPromise = null;
77
107
  }
78
- async signOut() {
79
- return gapi.auth2.getAuthInstance().signOut();
80
- }
81
- async addUserChangeListener() {
82
- await this.gapiLoaded;
83
- gapi.auth2.getAuthInstance().currentUser.listen((googleUser) => {
84
- this.notifyListeners('userChange', googleUser.isSignedIn() ? this.getUserFrom(googleUser) : null);
108
+ signOut() {
109
+ return new Promise((resolve) => {
110
+ google.accounts.id.cancel();
111
+ // When the user signs out of your website, you need to call the method disableAutoSelect to record the status in cookies. This prevents a UX dead loop.
112
+ google.accounts.id.disableAutoSelect();
113
+ if (this.authenticatedUserId) {
114
+ // Calling revoke method revokes all OAuth2 scopes previously granted by the Sign In With Google client library.
115
+ google.accounts.id.revoke(this.authenticatedUserId, response => {
116
+ if (response.successful) {
117
+ resolve({ isSuccess: true });
118
+ }
119
+ else {
120
+ resolve({ isSuccess: false, error: response.error });
121
+ }
122
+ });
123
+ this.authenticatedUserId = null;
124
+ }
125
+ else {
126
+ resolve({ isSuccess: true });
127
+ }
85
128
  });
86
129
  }
87
- getUserFrom(googleUser) {
88
- const user = {};
89
- const profile = googleUser.getBasicProfile();
90
- // user.email = profile.getEmail();
91
- // user.familyName = profile.getFamilyName();
92
- // user.givenName = profile.getGivenName();
93
- user.id = profile.getId();
94
- // user.imageUrl = profile.getImageUrl();
95
- // user.name = profile.getName();
96
- //const authResponse = googleUser.getAuthResponse(true);
97
- // user.authentication = {
98
- // accessToken: authResponse.access_token,
99
- // idToken: authResponse.id_token,
100
- // refreshToken: '',
101
- // };
102
- return user;
130
+ }
131
+ function assert(predicate) {
132
+ if (!predicate()) {
133
+ throw Error(`Assert error, expected '${predicate}' to be true.`);
103
134
  }
104
135
  }
105
136
  //# sourceMappingURL=web.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AACrC,OAAO,UAAU,MAAM,YAAY,CAAC;AAOpC,+EAA+E;AAC/E,MAAM,OAAO,mBAAoB,SAAQ,SAAS;IAAlD;;QACE,iBAAY,GAAG,wCAAwC,CAAC;QACxD,sBAAiB,GAAkB,IAAI,CAAC;QAIxC,wBAAmB,GAAW,IAAI,CAAC;IA2IrC,CAAC;IAzIC,UAAU;QACR,IAAI,IAAI,CAAC,iBAAiB,IAAI,IAAI,EAAE;YAClC,IAAI,CAAC,iBAAiB,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBACrD,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC;YACnC,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,UAAU,EAAE,CAAC;SACnB;QACD,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAChC,CAAC;IAEO,UAAU;QAChB,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE;YACnC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAAsB;QACxC,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,OAAsB;QAC9C,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,oCAAoC,CAAC,OAAsB;QAC/D,IAAI,YAAY,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAEtD,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE;YAC3B,YAAY,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;SACpD;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,eAAuB,EAAE,OAAsB,EAAE,sBAAsD;QACxH,MAAM,UAAU,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAC5D,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAA;QAE1B,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxB,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAEtC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,YAAY,CAC7B,UAAW,EACX,sBAAsB,IAAI,EAAE,CAC7B,CAAC;QACF,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,OAAsB,EAAE,UAAmB;QAChE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAEjC,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QACxB,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC3B,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAE3C,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,EAAE;YACzC,IAAI,YAAY,CAAC,cAAc,EAAE;mBAC5B,YAAY,CAAC,eAAe,EAAE;mBAC9B,YAAY,CAAC,iBAAiB,EAAE,EAAE;gBACrC,IAAI,CAAC,oBAAoB,CAAC;oBACxB,SAAS,EAAE,KAAK;oBAChB,mBAAmB,EAAE,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC;iBACxD,CAAC,CAAC;gBACH,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;aAC3B;QACH,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAEO,mBAAmB;QACzB,IAAI,CAAC,aAAa,GAAG,IAAI,OAAO,CAAe,CAAC,OAAO,EAAE,EAAE;YACzD,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC;QACtC,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,eAAe,CAAC,YAA6C;QACnE,IAAI,YAAY,CAAC,cAAc,EAAE,EAAE;YACjC,OAAO,YAAY,CAAC,qBAAqB,EAAE,CAAC;SAC7C;QACD,IAAI,YAAY,CAAC,eAAe,EAAE,EAAE;YAClC,OAAO,YAAY,CAAC,gBAAgB,EAAE,CAAC;SACxC;QACD,IAAI,YAAY,CAAC,iBAAiB,EAAE,EAAE;YACpC,OAAO,YAAY,CAAC,kBAAkB,EAAE,CAAC;SAC1C;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,gBAAgB,CAAC,OAAsB,EAAE,UAAmB;;QAClE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,UAAU,CAAC;YAC5B,SAAS,EAAE,OAAO,CAAC,QAAQ;YAC3B,QAAQ,EAAE,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC;YAClD,WAAW,EAAE,UAAU;YACvB,WAAW,EAAE,CAAA,MAAA,OAAO,CAAC,UAAU,0CAAE,UAAU,KAAI,KAAK;YACpD,qBAAqB,EAAE,KAAK;YAC5B,OAAO,EAAE,CAAA,MAAA,OAAO,CAAC,UAAU,0CAAE,MAAM,KAAI,OAAO;SAC/C,CAAC,CAAC;IACL,CAAC;IAEO,wBAAwB,CAAC,kBAA6C;QAC5E,MAAM,cAAc,GAAG,UAAU,CAAC,kBAAkB,CAAC,UAAU,CAAQ,CAAC;QACxE,IAAI,YAAY,GAAiB;YAC/B,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,kBAAkB,CAAC,UAAU;YACtC,KAAK,EAAE,cAAc,CAAC,KAAK;YAC3B,QAAQ,EAAE,kBAAkB,CAAC,SAAS;YACtC,cAAc,EAAE,cAAc;SAC/B,CAAC;QACF,IAAI,CAAC,mBAAmB,GAAG,cAAc,CAAC,KAAK,CAAW,CAAC;QAC3D,+BAA+B;QAC/B,IAAI,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC;QACxC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED,OAAO;QACL,OAAO,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,EAAE;YAC5C,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;YAE5B,yJAAyJ;YACzJ,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC;YAEvC,IAAI,IAAI,CAAC,mBAAmB,EAAE;gBAC5B,gHAAgH;gBAChH,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE,QAAQ,CAAC,EAAE;oBAC7D,IAAI,QAAQ,CAAC,UAAU,EAAE;wBACvB,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;qBAC9B;yBACI;wBACH,OAAO,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;qBACtD;gBACH,CAAC,CAAC,CAAC;gBACH,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;aACjC;iBAAM;gBACL,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;aAC9B;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAED,SAAS,MAAM,CAAC,SAAwB;IACtC,IAAI,CAAC,SAAS,EAAE,EAAE;QAChB,MAAM,KAAK,CAAC,2BAA2B,SAAS,eAAe,CAAC,CAAC;KAClE;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-native-google-one-tap-signin",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Google One Tap sign-in plugin for capacitor.",
5
5
  "main": "dist/esm/index.js",
6
6
  "types": "dist/esm/index.d.ts",
@@ -21,6 +21,7 @@
21
21
  "@ionic/prettier-config": "^2.0.0",
22
22
  "@types/gapi": "^0.0.44",
23
23
  "@types/gapi.auth2": "^0.0.57",
24
+ "@types/google-one-tap": "^1.2.2",
24
25
  "prettier": "^2.8.3",
25
26
  "typescript": "^4.9.5"
26
27
  },
@@ -60,5 +61,10 @@
60
61
  "bugs": {
61
62
  "url": "https://github.com/inouiw/capacitor-native-google-one-tap-signin/issues"
62
63
  },
63
- "prettier": "@ionic/prettier-config"
64
+ "prettier": "@ionic/prettier-config",
65
+ "dependencies": {
66
+ "@types/scriptjs": "^0.0.2",
67
+ "jwt-decode": "^3.1.2",
68
+ "scriptjs": "^2.5.9"
69
+ }
64
70
  }
File without changes
Binary file
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="CompilerConfiguration">
4
- <bytecodeTargetLevel target="11" />
5
- </component>
6
- </project>
@@ -1,19 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="GradleMigrationSettings" migrationVersion="1" />
4
- <component name="GradleSettings">
5
- <option name="linkedExternalProjectsSettings">
6
- <GradleProjectSettings>
7
- <option name="testRunner" value="GRADLE" />
8
- <option name="distributionType" value="DEFAULT_WRAPPED" />
9
- <option name="externalProjectPath" value="$PROJECT_DIR$" />
10
- <option name="modules">
11
- <set>
12
- <option value="$PROJECT_DIR$" />
13
- <option value="$PROJECT_DIR$/../node_modules/@capacitor/android/capacitor" />
14
- </set>
15
- </option>
16
- </GradleProjectSettings>
17
- </option>
18
- </component>
19
- </project>
@@ -1,30 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="RemoteRepositoriesConfiguration">
4
- <remote-repository>
5
- <option name="id" value="central" />
6
- <option name="name" value="Maven Central repository" />
7
- <option name="url" value="https://repo1.maven.org/maven2" />
8
- </remote-repository>
9
- <remote-repository>
10
- <option name="id" value="jboss.community" />
11
- <option name="name" value="JBoss Community repository" />
12
- <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
13
- </remote-repository>
14
- <remote-repository>
15
- <option name="id" value="MavenRepo" />
16
- <option name="name" value="MavenRepo" />
17
- <option name="url" value="https://repo.maven.apache.org/maven2/" />
18
- </remote-repository>
19
- <remote-repository>
20
- <option name="id" value="BintrayJCenter" />
21
- <option name="name" value="BintrayJCenter" />
22
- <option name="url" value="https://jcenter.bintray.com/" />
23
- </remote-repository>
24
- <remote-repository>
25
- <option name="id" value="Google" />
26
- <option name="name" value="Google" />
27
- <option name="url" value="https://dl.google.com/dl/android/maven2/" />
28
- </remote-repository>
29
- </component>
30
- </project>
@@ -1,10 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ExternalStorageConfigurationManager" enabled="true" />
4
- <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
5
- <output url="file://$PROJECT_DIR$/build/classes" />
6
- </component>
7
- <component name="ProjectType">
8
- <option name="id" value="Android" />
9
- </component>
10
- </project>
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="VcsDirectoryMappings">
4
- <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
5
- </component>
6
- </project>
@@ -1,8 +0,0 @@
1
- ## This file must *NOT* be checked into Version Control Systems,
2
- # as it contains information specific to your local configuration.
3
- #
4
- # Location of the SDK. This is only used by Gradle.
5
- # For customization when using a Version Control System, please read the
6
- # header note.
7
- #Fri Jan 27 18:41:51 CET 2023
8
- sdk.dir=/Users/davidneuy/Library/Android/sdk