@capgo/capacitor-autofill-save-password 7.0.1
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.
- package/CapgoCapacitorAutofillSavePassword.podspec +17 -0
- package/Package.swift +28 -0
- package/README.md +89 -0
- package/android/build.gradle +61 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/ee/forgr/autofill_password/SavePasswordPlugin.java +78 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +88 -0
- package/dist/esm/definitions.d.ts +31 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +5 -0
- package/dist/esm/web.js +7 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +21 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +24 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/SavePasswordPlugin/SavePasswordPlugin.swift +53 -0
- package/ios/Tests/SavePasswordPluginTests/SavePasswordPluginTests.swift +15 -0
- package/package.json +85 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'CapgoCapacitorAutofillSavePassword'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.license = package['license']
|
|
10
|
+
s.homepage = package['repository']['url']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
|
|
13
|
+
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
|
+
s.ios.deployment_target = '14.0'
|
|
15
|
+
s.dependency 'Capacitor'
|
|
16
|
+
s.swift_version = '5.1'
|
|
17
|
+
end
|
package/Package.swift
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// swift-tools-version: 5.9
|
|
2
|
+
import PackageDescription
|
|
3
|
+
|
|
4
|
+
let package = Package(
|
|
5
|
+
name: "CapgoCapacitorAutofillSavePassword",
|
|
6
|
+
platforms: [.iOS(.v14)],
|
|
7
|
+
products: [
|
|
8
|
+
.library(
|
|
9
|
+
name: "CapgoCapacitorAutofillSavePassword",
|
|
10
|
+
targets: ["SavePasswordPlugin"])
|
|
11
|
+
],
|
|
12
|
+
dependencies: [
|
|
13
|
+
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0")
|
|
14
|
+
],
|
|
15
|
+
targets: [
|
|
16
|
+
.target(
|
|
17
|
+
name: "SavePasswordPlugin",
|
|
18
|
+
dependencies: [
|
|
19
|
+
.product(name: "Capacitor", package: "capacitor-swift-pm"),
|
|
20
|
+
.product(name: "Cordova", package: "capacitor-swift-pm")
|
|
21
|
+
],
|
|
22
|
+
path: "ios/Sources/SavePasswordPlugin"),
|
|
23
|
+
.testTarget(
|
|
24
|
+
name: "SavePasswordPluginTests",
|
|
25
|
+
dependencies: ["SavePasswordPlugin"],
|
|
26
|
+
path: "ios/Tests/SavePasswordPluginTests")
|
|
27
|
+
]
|
|
28
|
+
)
|
package/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# @capgo/capacitor-autofill-save-password
|
|
2
|
+
|
|
3
|
+
Prompt to display dialog for saving password to keychain from webview app
|
|
4
|
+
|
|
5
|
+
<a href="https://capgo.app/"><img src='https://raw.githubusercontent.com/Cap-go/capgo/main/assets/capgo_banner.png' alt='Capgo - Instant updates for capacitor'/></a>
|
|
6
|
+
|
|
7
|
+
<div align="center">
|
|
8
|
+
<h2><a href="https://capgo.app/?ref=plugin"> ➡️ Get Instant updates for your App with Capgo 🚀</a></h2>
|
|
9
|
+
<h2><a href="https://capgo.app/consulting/?ref=plugin"> Fix your annoying bug now, Hire a Capacitor expert 💪</a></h2>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
Fork of original plugin to work with Capacitor 7
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @capgo/capacitor-autofill-save-password
|
|
18
|
+
npx cap sync
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Prerequisite
|
|
22
|
+
You must set up your app’s associated domains. To learn how to set up your app’s associated domains, see [Supporting Associated Domains](https://developer.apple.com/documentation/safariservices/supporting_associated_domains) in Apple Developer document.
|
|
23
|
+
|
|
24
|
+
Then add in your `App.entitlements`
|
|
25
|
+
|
|
26
|
+
```xml
|
|
27
|
+
<key>com.apple.developer.associated-domains</key>
|
|
28
|
+
<array>
|
|
29
|
+
<string>webcredentials:YOURDOMAIN</string>
|
|
30
|
+
</array>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
To associate your domain to your app.
|
|
34
|
+
|
|
35
|
+
## How to use
|
|
36
|
+
```ts
|
|
37
|
+
import { Capacitor } from '@capacitor/core';
|
|
38
|
+
import { SavePassword } from '@capgo/capacitor-autofill-save-password';
|
|
39
|
+
|
|
40
|
+
login(username: string, password: string) {
|
|
41
|
+
// your login logic here
|
|
42
|
+
|
|
43
|
+
SavePassword.promptDialog({
|
|
44
|
+
username: username,
|
|
45
|
+
password: password,
|
|
46
|
+
})
|
|
47
|
+
.then(() => console.log('promptDialog success'))
|
|
48
|
+
.catch((err) => console.error('promptDialog failure', err));
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## API
|
|
53
|
+
|
|
54
|
+
<docgen-index>
|
|
55
|
+
|
|
56
|
+
* [`promptDialog(...)`](#promptdialog)
|
|
57
|
+
* [Interfaces](#interfaces)
|
|
58
|
+
|
|
59
|
+
</docgen-index>
|
|
60
|
+
|
|
61
|
+
<docgen-api>
|
|
62
|
+
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
63
|
+
|
|
64
|
+
### promptDialog(...)
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
promptDialog(options: Options) => Promise<void>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Save a password to the keychain.
|
|
71
|
+
|
|
72
|
+
| Param | Type | Description |
|
|
73
|
+
| ------------- | ------------------------------------------- | ------------------------------- |
|
|
74
|
+
| **`options`** | <code><a href="#options">Options</a></code> | - The options for the password. |
|
|
75
|
+
|
|
76
|
+
--------------------
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
### Interfaces
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
#### Options
|
|
83
|
+
|
|
84
|
+
| Prop | Type | Description |
|
|
85
|
+
| -------------- | ------------------- | --------------------- |
|
|
86
|
+
| **`username`** | <code>string</code> | The username to save. |
|
|
87
|
+
| **`password`** | <code>string</code> | The password to save. |
|
|
88
|
+
|
|
89
|
+
</docgen-api>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
ext {
|
|
2
|
+
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
|
3
|
+
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
|
|
4
|
+
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
|
|
5
|
+
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
buildscript {
|
|
9
|
+
repositories {
|
|
10
|
+
google()
|
|
11
|
+
mavenCentral()
|
|
12
|
+
}
|
|
13
|
+
dependencies {
|
|
14
|
+
classpath 'com.android.tools.build:gradle:8.7.2'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
apply plugin: 'com.android.library'
|
|
19
|
+
|
|
20
|
+
android {
|
|
21
|
+
namespace "ee.forgr.autofill_password"
|
|
22
|
+
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
|
|
23
|
+
defaultConfig {
|
|
24
|
+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
|
|
25
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
|
|
26
|
+
versionCode 1
|
|
27
|
+
versionName "1.0"
|
|
28
|
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
29
|
+
}
|
|
30
|
+
buildTypes {
|
|
31
|
+
release {
|
|
32
|
+
minifyEnabled false
|
|
33
|
+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
lintOptions {
|
|
37
|
+
abortOnError false
|
|
38
|
+
}
|
|
39
|
+
compileOptions {
|
|
40
|
+
sourceCompatibility JavaVersion.VERSION_21
|
|
41
|
+
targetCompatibility JavaVersion.VERSION_21
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
repositories {
|
|
46
|
+
google()
|
|
47
|
+
mavenCentral()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
dependencies {
|
|
52
|
+
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
53
|
+
implementation project(':capacitor-android')
|
|
54
|
+
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
55
|
+
implementation(libs.androidx.credentials)
|
|
56
|
+
implementation(libs.androidx.credentials.play.services.auth)
|
|
57
|
+
// implementation 'androidx.credentials:credentials:1.5.0'
|
|
58
|
+
testImplementation "junit:junit:$junitVersion"
|
|
59
|
+
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
60
|
+
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
61
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
package ee.forgr.autofill_password;
|
|
2
|
+
|
|
3
|
+
import com.getcapacitor.JSObject;
|
|
4
|
+
import com.getcapacitor.Plugin;
|
|
5
|
+
import com.getcapacitor.PluginCall;
|
|
6
|
+
import com.getcapacitor.PluginMethod;
|
|
7
|
+
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
8
|
+
import android.util.Log;
|
|
9
|
+
import android.os.CancellationSignal;
|
|
10
|
+
import androidx.credentials.CredentialManager;
|
|
11
|
+
import androidx.credentials.CredentialManagerCallback;
|
|
12
|
+
import androidx.credentials.CreatePasswordRequest;
|
|
13
|
+
import androidx.credentials.CreateCredentialResponse;
|
|
14
|
+
import androidx.credentials.exceptions.CreateCredentialException;
|
|
15
|
+
import java.util.concurrent.Executor;
|
|
16
|
+
|
|
17
|
+
@CapacitorPlugin(name = "SavePassword")
|
|
18
|
+
public class SavePasswordPlugin extends Plugin {
|
|
19
|
+
|
|
20
|
+
private static final String TAG = "SavePasswordPlugin";
|
|
21
|
+
|
|
22
|
+
@PluginMethod
|
|
23
|
+
public void promptDialog(PluginCall call) {
|
|
24
|
+
String username = call.getString("username");
|
|
25
|
+
String password = call.getString("password");
|
|
26
|
+
|
|
27
|
+
if (username == null || username.isEmpty()) {
|
|
28
|
+
call.reject("Username cannot be empty.");
|
|
29
|
+
Log.w(TAG, "Username was null or empty.");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (password == null) {
|
|
34
|
+
call.reject("Password cannot be null. Provide an empty string if the password is meant to be empty.");
|
|
35
|
+
Log.w(TAG, "Password was null.");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (getActivity() == null) {
|
|
40
|
+
call.reject("Activity is not available to show dialog.");
|
|
41
|
+
Log.e(TAG, "Activity was null, cannot access CredentialManager.");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Build the CreatePasswordRequest
|
|
46
|
+
CreatePasswordRequest createPasswordRequest = new CreatePasswordRequest(username, password);
|
|
47
|
+
|
|
48
|
+
// Get the CredentialManager instance
|
|
49
|
+
CredentialManager credentialManager = CredentialManager.create(getActivity());
|
|
50
|
+
|
|
51
|
+
// Set up executor and cancellation signal
|
|
52
|
+
Executor executor = getActivity().getMainExecutor();
|
|
53
|
+
CancellationSignal cancellationSignal = new CancellationSignal();
|
|
54
|
+
|
|
55
|
+
credentialManager.createCredentialAsync(
|
|
56
|
+
getActivity(),
|
|
57
|
+
createPasswordRequest,
|
|
58
|
+
cancellationSignal,
|
|
59
|
+
executor,
|
|
60
|
+
new CredentialManagerCallback<CreateCredentialResponse, CreateCredentialException>() {
|
|
61
|
+
@Override
|
|
62
|
+
public void onResult(CreateCredentialResponse result) {
|
|
63
|
+
JSObject response = new JSObject();
|
|
64
|
+
response.put("prompted", true);
|
|
65
|
+
Log.d(TAG, "Password save prompt completed successfully.");
|
|
66
|
+
call.resolve(response);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@Override
|
|
70
|
+
public void onError(CreateCredentialException e) {
|
|
71
|
+
String errorMessage = "Failed to save password credential: " + e.getMessage();
|
|
72
|
+
Log.e(TAG, errorMessage, e);
|
|
73
|
+
call.reject(errorMessage, e);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
File without changes
|
package/dist/docs.json
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"api": {
|
|
3
|
+
"name": "SavePasswordPlugin",
|
|
4
|
+
"slug": "savepasswordplugin",
|
|
5
|
+
"docs": "",
|
|
6
|
+
"tags": [
|
|
7
|
+
{
|
|
8
|
+
"text": "SavePasswordPlugin",
|
|
9
|
+
"name": "interface"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"text": "Capacitor plugin for saving passwords to the keychain.",
|
|
13
|
+
"name": "description"
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"methods": [
|
|
17
|
+
{
|
|
18
|
+
"name": "promptDialog",
|
|
19
|
+
"signature": "(options: Options) => Promise<void>",
|
|
20
|
+
"parameters": [
|
|
21
|
+
{
|
|
22
|
+
"name": "options",
|
|
23
|
+
"docs": "- The options for the password.",
|
|
24
|
+
"type": "Options"
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"returns": "Promise<void>",
|
|
28
|
+
"tags": [
|
|
29
|
+
{
|
|
30
|
+
"name": "param",
|
|
31
|
+
"text": "options - The options for the password."
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "returns",
|
|
35
|
+
"text": "Success status"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "example",
|
|
39
|
+
"text": "await SavePassword.promptDialog({\n username: 'your-username',\n password: 'your-password'\n});"
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"docs": "Save a password to the keychain.",
|
|
43
|
+
"complexTypes": [
|
|
44
|
+
"Options"
|
|
45
|
+
],
|
|
46
|
+
"slug": "promptdialog"
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"properties": []
|
|
50
|
+
},
|
|
51
|
+
"interfaces": [
|
|
52
|
+
{
|
|
53
|
+
"name": "Options",
|
|
54
|
+
"slug": "options",
|
|
55
|
+
"docs": "",
|
|
56
|
+
"tags": [
|
|
57
|
+
{
|
|
58
|
+
"text": "Options",
|
|
59
|
+
"name": "interface"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"text": "The options for the prompt.",
|
|
63
|
+
"name": "description"
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"methods": [],
|
|
67
|
+
"properties": [
|
|
68
|
+
{
|
|
69
|
+
"name": "username",
|
|
70
|
+
"tags": [],
|
|
71
|
+
"docs": "The username to save.",
|
|
72
|
+
"complexTypes": [],
|
|
73
|
+
"type": "string"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"name": "password",
|
|
77
|
+
"tags": [],
|
|
78
|
+
"docs": "The password to save.",
|
|
79
|
+
"complexTypes": [],
|
|
80
|
+
"type": "string"
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"enums": [],
|
|
86
|
+
"typeAliases": [],
|
|
87
|
+
"pluginConfigs": []
|
|
88
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @interface Options
|
|
3
|
+
* @description The options for the prompt.
|
|
4
|
+
*/
|
|
5
|
+
export interface Options {
|
|
6
|
+
/**
|
|
7
|
+
* The username to save.
|
|
8
|
+
*/
|
|
9
|
+
username: string;
|
|
10
|
+
/**
|
|
11
|
+
* The password to save.
|
|
12
|
+
*/
|
|
13
|
+
password: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* @interface SavePasswordPlugin
|
|
17
|
+
* @description Capacitor plugin for saving passwords to the keychain.
|
|
18
|
+
*/
|
|
19
|
+
export interface SavePasswordPlugin {
|
|
20
|
+
/**
|
|
21
|
+
* Save a password to the keychain.
|
|
22
|
+
* @param {Options} options - The options for the password.
|
|
23
|
+
* @returns {Promise<void>} Success status
|
|
24
|
+
* @example
|
|
25
|
+
* await SavePassword.promptDialog({
|
|
26
|
+
* username: 'your-username',
|
|
27
|
+
* password: 'your-password'
|
|
28
|
+
* });
|
|
29
|
+
*/
|
|
30
|
+
promptDialog(options: Options): Promise<void>;
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * @interface Options\n * @description The options for the prompt.\n */\nexport interface Options {\n /**\n * The username to save.\n */\n username: string;\n /**\n * The password to save.\n */\n password: string;\n}\n\n/**\n * @interface SavePasswordPlugin\n * @description Capacitor plugin for saving passwords to the keychain.\n */\nexport interface SavePasswordPlugin {\n /**\n * Save a password to the keychain.\n * @param {Options} options - The options for the password.\n * @returns {Promise<void>} Success status\n * @example\n * await SavePassword.promptDialog({\n * username: 'your-username',\n * password: 'your-password'\n * });\n */\n promptDialog(options: Options): Promise<void>;\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { registerPlugin } from '@capacitor/core';
|
|
2
|
+
const SavePassword = registerPlugin('SavePassword', {
|
|
3
|
+
web: () => import('./web').then((m) => new m.SavePasswordWeb()),
|
|
4
|
+
});
|
|
5
|
+
export * from './definitions';
|
|
6
|
+
export { SavePassword };
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,YAAY,GAAG,cAAc,CAAqB,cAAc,EAAE;IACtE,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC;CAChE,CAAC,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,CAAC","sourcesContent":["import { registerPlugin } from '@capacitor/core';\n\nimport type { SavePasswordPlugin } from './definitions';\n\nconst SavePassword = registerPlugin<SavePasswordPlugin>('SavePassword', {\n web: () => import('./web').then((m) => new m.SavePasswordWeb()),\n});\n\nexport * from './definitions';\nexport { SavePassword };\n"]}
|
package/dist/esm/web.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,OAAO,eAAgB,SAAQ,SAAS;IAC5C,KAAK,CAAC,YAAY,CAAC,OAAgB;QACjC,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACtE,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type { Options, SavePasswordPlugin } from './definitions';\n\nexport class SavePasswordWeb extends WebPlugin implements SavePasswordPlugin {\n async promptDialog(options: Options): Promise<void> {\n throw new Error(\"Not implemented on web\" + JSON.stringify(options));\n }\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@capacitor/core');
|
|
4
|
+
|
|
5
|
+
const SavePassword = core.registerPlugin('SavePassword', {
|
|
6
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.SavePasswordWeb()),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
class SavePasswordWeb extends core.WebPlugin {
|
|
10
|
+
async promptDialog(options) {
|
|
11
|
+
throw new Error("Not implemented on web" + JSON.stringify(options));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
16
|
+
__proto__: null,
|
|
17
|
+
SavePasswordWeb: SavePasswordWeb
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
exports.SavePassword = SavePassword;
|
|
21
|
+
//# sourceMappingURL=plugin.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst SavePassword = registerPlugin('SavePassword', {\n web: () => import('./web').then((m) => new m.SavePasswordWeb()),\n});\nexport * from './definitions';\nexport { SavePassword };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class SavePasswordWeb extends WebPlugin {\n async promptDialog(options) {\n throw new Error(\"Not implemented on web\" + JSON.stringify(options));\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,YAAY,GAAGA,mBAAc,CAAC,cAAc,EAAE;AACpD,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC;AACnE,CAAC;;ACFM,MAAM,eAAe,SAASC,cAAS,CAAC;AAC/C,IAAI,MAAM,YAAY,CAAC,OAAO,EAAE;AAChC,QAAQ,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AAC3E;AACA;;;;;;;;;"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
var capacitorSavePassword = (function (exports, core) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const SavePassword = core.registerPlugin('SavePassword', {
|
|
5
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.SavePasswordWeb()),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
class SavePasswordWeb extends core.WebPlugin {
|
|
9
|
+
async promptDialog(options) {
|
|
10
|
+
throw new Error("Not implemented on web" + JSON.stringify(options));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
var web = /*#__PURE__*/Object.freeze({
|
|
15
|
+
__proto__: null,
|
|
16
|
+
SavePasswordWeb: SavePasswordWeb
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
exports.SavePassword = SavePassword;
|
|
20
|
+
|
|
21
|
+
return exports;
|
|
22
|
+
|
|
23
|
+
})({}, capacitorExports);
|
|
24
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst SavePassword = registerPlugin('SavePassword', {\n web: () => import('./web').then((m) => new m.SavePasswordWeb()),\n});\nexport * from './definitions';\nexport { SavePassword };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class SavePasswordWeb extends WebPlugin {\n async promptDialog(options) {\n throw new Error(\"Not implemented on web\" + JSON.stringify(options));\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,YAAY,GAAGA,mBAAc,CAAC,cAAc,EAAE;IACpD,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC;IACnE,CAAC;;ICFM,MAAM,eAAe,SAASC,cAAS,CAAC;IAC/C,IAAI,MAAM,YAAY,CAAC,OAAO,EAAE;IAChC,QAAQ,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3E;IACA;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Please read the Capacitor iOS Plugin Development Guide
|
|
6
|
+
* here: https://capacitorjs.com/docs/plugins/ios
|
|
7
|
+
*/
|
|
8
|
+
@objc(SavePasswordPlugin)
|
|
9
|
+
public class SavePasswordPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
10
|
+
public let identifier = "SavePasswordPlugin"
|
|
11
|
+
|
|
12
|
+
public let jsName = "SavePassword"
|
|
13
|
+
public let pluginMethods: [CAPPluginMethod] = [
|
|
14
|
+
CAPPluginMethod(name: "promptDialog", returnType: CAPPluginReturnPromise)
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
@objc func promptDialog(_ call: CAPPluginCall) {
|
|
18
|
+
DispatchQueue.main.async {
|
|
19
|
+
let loginScreen = LoginScreenViewController()
|
|
20
|
+
loginScreen.usernameTextField.text = call.getString("username") ?? ""
|
|
21
|
+
loginScreen.passwordTextField.text = call.getString("password") ?? ""
|
|
22
|
+
self.bridge?.webView?.addSubview(loginScreen.view)
|
|
23
|
+
loginScreen.view.removeFromSuperview()
|
|
24
|
+
call.resolve()
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
class LoginScreenViewController: UIViewController {
|
|
30
|
+
let usernameTextField: UITextField = {
|
|
31
|
+
let textField = UITextField()
|
|
32
|
+
textField.frame.size.width = 1
|
|
33
|
+
textField.frame.size.height = 1
|
|
34
|
+
textField.textContentType = .username
|
|
35
|
+
return textField
|
|
36
|
+
}()
|
|
37
|
+
|
|
38
|
+
let passwordTextField: UITextField = {
|
|
39
|
+
let textField = UITextField()
|
|
40
|
+
textField.frame.size.width = 1
|
|
41
|
+
textField.frame.size.height = 1
|
|
42
|
+
textField.textContentType = .newPassword
|
|
43
|
+
return textField
|
|
44
|
+
}()
|
|
45
|
+
|
|
46
|
+
override func viewDidLoad() {
|
|
47
|
+
super.viewDidLoad()
|
|
48
|
+
view.frame = CGRect(x: 0, y: 0, width: 0, height: 0)
|
|
49
|
+
view.addSubview(usernameTextField)
|
|
50
|
+
view.addSubview(passwordTextField)
|
|
51
|
+
usernameTextField.becomeFirstResponder()
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import XCTest
|
|
2
|
+
@testable import SavePasswordPlugin
|
|
3
|
+
|
|
4
|
+
class SavePasswordTests: XCTestCase {
|
|
5
|
+
func testEcho() {
|
|
6
|
+
// This is an example of a functional test case for a plugin.
|
|
7
|
+
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
|
8
|
+
|
|
9
|
+
let implementation = SavePassword()
|
|
10
|
+
let value = "Hello, World!"
|
|
11
|
+
let result = implementation.echo(value)
|
|
12
|
+
|
|
13
|
+
XCTAssertEqual(value, result)
|
|
14
|
+
}
|
|
15
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@capgo/capacitor-autofill-save-password",
|
|
3
|
+
"version": "7.0.1",
|
|
4
|
+
"description": "Prompt to display dialog for saving password to keychain from webview app",
|
|
5
|
+
"main": "dist/plugin.cjs.js",
|
|
6
|
+
"module": "dist/esm/index.js",
|
|
7
|
+
"types": "dist/esm/index.d.ts",
|
|
8
|
+
"unpkg": "dist/plugin.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"android/src/main/",
|
|
11
|
+
"android/build.gradle",
|
|
12
|
+
"dist/",
|
|
13
|
+
"ios/Sources",
|
|
14
|
+
"ios/Tests",
|
|
15
|
+
"Package.swift",
|
|
16
|
+
"CapgoCapacitorAutofillSavePassword.podspec"
|
|
17
|
+
],
|
|
18
|
+
"author": "Martin Donadieu <martin@capgo.app>",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/Cap-go/capacitor-autofill-save-password.git"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/Cap-go/capacitor-autofill-save-password/issues"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"capacitor",
|
|
29
|
+
"plugin",
|
|
30
|
+
"native",
|
|
31
|
+
"autofill",
|
|
32
|
+
"save",
|
|
33
|
+
"password",
|
|
34
|
+
"ios",
|
|
35
|
+
"android"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
|
|
39
|
+
"verify:ios": "xcodebuild -scheme CapgoCapacitorAutofillSavePassword -destination generic/platform=iOS",
|
|
40
|
+
"verify:android": "cd android && ./gradlew clean build test && cd ..",
|
|
41
|
+
"verify:web": "npm run build",
|
|
42
|
+
"lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
|
|
43
|
+
"fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
|
|
44
|
+
"eslint": "eslint . --ext ts",
|
|
45
|
+
"prettier": "prettier \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
|
|
46
|
+
"swiftlint": "node-swiftlint",
|
|
47
|
+
"docgen": "docgen --api SavePasswordPlugin --output-readme README.md --output-json dist/docs.json",
|
|
48
|
+
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
|
|
49
|
+
"clean": "rimraf ./dist",
|
|
50
|
+
"watch": "tsc --watch",
|
|
51
|
+
"prepublishOnly": "npm run build"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@capacitor/android": "^7.0.0",
|
|
55
|
+
"@capacitor/core": "^7.0.0",
|
|
56
|
+
"@capacitor/docgen": "^0.3.0",
|
|
57
|
+
"@capacitor/ios": "^7.0.0",
|
|
58
|
+
"@ionic/eslint-config": "^0.4.0",
|
|
59
|
+
"@ionic/prettier-config": "^4.0.0",
|
|
60
|
+
"@ionic/swiftlint-config": "^2.0.0",
|
|
61
|
+
"eslint": "^8.57.0",
|
|
62
|
+
"prettier": "^3.4.2",
|
|
63
|
+
"prettier-plugin-java": "^2.6.6",
|
|
64
|
+
"rimraf": "^6.0.1",
|
|
65
|
+
"rollup": "^4.30.1",
|
|
66
|
+
"swiftlint": "^2.0.0",
|
|
67
|
+
"typescript": "~4.1.5"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"@capacitor/core": ">=7.0.0"
|
|
71
|
+
},
|
|
72
|
+
"prettier": "@ionic/prettier-config",
|
|
73
|
+
"swiftlint": "@ionic/swiftlint-config",
|
|
74
|
+
"eslintConfig": {
|
|
75
|
+
"extends": "@ionic/eslint-config/recommended"
|
|
76
|
+
},
|
|
77
|
+
"capacitor": {
|
|
78
|
+
"ios": {
|
|
79
|
+
"src": "ios"
|
|
80
|
+
},
|
|
81
|
+
"android": {
|
|
82
|
+
"src": "android"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|