mirror of
https://github.com/bitwarden/mobile
synced 2025-12-12 06:13:21 +00:00
Compare commits
37 Commits
v2.14.2
...
feature/io
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69cd7d79e7 | ||
|
|
dbf94c1b56 | ||
|
|
4b0fb2840e | ||
|
|
629c696c81 | ||
|
|
bf1aa7c4eb | ||
|
|
318a3e4de9 | ||
|
|
0f992d27b3 | ||
|
|
83fd6736f6 | ||
|
|
397250368a | ||
|
|
5e4365084b | ||
|
|
ea5e4aafa3 | ||
|
|
69d1de47c6 | ||
|
|
0d3f819e93 | ||
|
|
3760e0f9f4 | ||
|
|
5a13cb53ba | ||
|
|
0e9cbe4539 | ||
|
|
b8c1107c94 | ||
|
|
a07ef1a1d6 | ||
|
|
99ccd62bcd | ||
|
|
bfb050a6f9 | ||
|
|
4e0b05571d | ||
|
|
d93d70fd66 | ||
|
|
41098ff05b | ||
|
|
4ed7491116 | ||
|
|
1ebad6bca5 | ||
|
|
48e3986264 | ||
|
|
88a1d8d4e8 | ||
|
|
f3ff991abe | ||
|
|
17b89dc21c | ||
|
|
ff76a3ec15 | ||
|
|
3a2e012c42 | ||
|
|
a0bb16c35f | ||
|
|
62a8d1c017 | ||
|
|
ce4e3ed1cd | ||
|
|
4669275680 | ||
|
|
fc1000acc1 | ||
|
|
c9ce7256e5 |
32
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
32
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
## Type of change
|
||||
- [ ] Bug fix
|
||||
- [ ] New feature development
|
||||
- [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc)
|
||||
- [ ] Build/deploy pipeline (DevOps)
|
||||
- [ ] Other
|
||||
|
||||
## Objective
|
||||
<!--Describe what the purpose of this PR is. For example: what bug you're fixing or what new feature you're adding-->
|
||||
|
||||
|
||||
|
||||
## Code changes
|
||||
<!--Explain the changes you've made to each file or major component. This should help the reviewer understand your changes-->
|
||||
<!--Also refer to any related changes or PRs in other repositories-->
|
||||
|
||||
* **file.ext:** Description of what was changed and why
|
||||
|
||||
## Screenshots
|
||||
<!--Required for any UI changes. Delete if not applicable-->
|
||||
|
||||
|
||||
|
||||
## Testing requirements
|
||||
<!--What functionality requires testing by QA? This includes testing new behavior and regression testing-->
|
||||
|
||||
|
||||
|
||||
## Before you submit
|
||||
- [ ] I have added **unit tests** where it makes sense to do so (encouraged but not required)
|
||||
- [ ] This change requires a **documentation update** (notify the documentation team)
|
||||
- [ ] This change has particular **deployment requirements** (notify the DevOps team)
|
||||
51
.github/workflows/build.yml
vendored
51
.github/workflows/build.yml
vendored
@@ -484,3 +484,54 @@ jobs:
|
||||
xcrun altool --upload-app --type ios --file "./bitwarden-export/Bitwarden.ipa" \
|
||||
--username "$APPLE_ID_USERNAME" --password "$APPLE_ID_PASSWORD"
|
||||
shell: bash
|
||||
|
||||
|
||||
check-failures:
|
||||
name: Check for failures
|
||||
if: always()
|
||||
runs-on: ubuntu-20.04
|
||||
needs:
|
||||
- cloc
|
||||
- android
|
||||
- f-droid
|
||||
- ios
|
||||
steps:
|
||||
- name: Check if any job failed
|
||||
if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }}
|
||||
env:
|
||||
CLOC_STATUS: ${{ needs.cloc.result }}
|
||||
ANDROID_STATUS: ${{ needs.android.result }}
|
||||
F_DROID_STATUS: ${{ needs.f-droid.result }}
|
||||
IOS_STATUS: ${{ needs.ios.result }}
|
||||
run: |
|
||||
if [ "$CLOC_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$ANDROID_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$F_DROID_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
elif [ "$IOS_STATUS" = "failure" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Login to Azure - Prod Subscription
|
||||
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
|
||||
if: failure()
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
|
||||
|
||||
- name: Retrieve secrets
|
||||
id: retrieve-secrets
|
||||
uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403
|
||||
if: failure()
|
||||
with:
|
||||
keyvault: "bitwarden-prod-kv"
|
||||
secrets: "devops-alerts-slack-webhook-url"
|
||||
|
||||
- name: Notify Slack on failure
|
||||
uses: act10ns/slack@e4e71685b9b239384b0f676a63c32367f59c2522 # v1.2.2
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -61,7 +61,7 @@ jobs:
|
||||
./Bitwarden.ipa/Bitwarden.ipa"
|
||||
commit: ${{ github.sha }}
|
||||
tag: v${{ steps.retrieve-mobile-version.outputs.mobile_version }}
|
||||
name: Test Version ${{ steps.retrieve-mobile-version.outputs.mobile_version }}
|
||||
name: Version ${{ steps.retrieve-mobile-version.outputs.mobile_version }}
|
||||
body: "<insert release notes here>"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
draft: true
|
||||
|
||||
@@ -44,6 +44,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "test\Common\Commo
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Test", "test\Core.Test\Core.Test.csproj", "{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Safari", "src\iOS.Safari\iOS.Safari.csproj", "{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
|
||||
@@ -414,6 +416,36 @@ Global
|
||||
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhone.Build.0 = Release|Any CPU
|
||||
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
|
||||
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Ad-Hoc|Any CPU.ActiveCfg = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Ad-Hoc|Any CPU.Build.0 = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Ad-Hoc|iPhone.ActiveCfg = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Ad-Hoc|iPhone.Build.0 = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.AppStore|Any CPU.ActiveCfg = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.AppStore|Any CPU.Build.0 = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.AppStore|iPhone.ActiveCfg = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.AppStore|iPhone.Build.0 = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.AppStore|iPhoneSimulator.ActiveCfg = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.AppStore|iPhoneSimulator.Build.0 = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Debug|Any CPU.ActiveCfg = Debug|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Debug|Any CPU.Build.0 = Debug|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Debug|iPhone.ActiveCfg = Debug|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Debug|iPhone.Build.0 = Debug|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.FDroid|Any CPU.ActiveCfg = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.FDroid|Any CPU.Build.0 = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.FDroid|iPhone.ActiveCfg = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.FDroid|iPhone.Build.0 = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.FDroid|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.FDroid|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Release|Any CPU.ActiveCfg = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Release|Any CPU.Build.0 = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Release|iPhone.ActiveCfg = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Release|iPhone.Build.0 = Release|iPhone
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -431,6 +463,7 @@ Global
|
||||
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A} = {D10CA4A9-F866-40E1-B658-F69051236C71}
|
||||
{4085B0A5-12A9-4993-B8B8-4ACE72E62E39} = {8904C536-C67D-420F-9971-51B26574C3AA}
|
||||
{8AE548D9-A567-4E97-995E-93EC7DB0FDE0} = {8904C536-C67D-420F-9971-51B26574C3AA}
|
||||
{7CE47211-43D4-4BBB-BB16-82A8A337ECE7} = {D10CA4A9-F866-40E1-B658-F69051236C71}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {7D436EA3-8B7E-45D2-8D14-0730BD2E0410}
|
||||
|
||||
710
package-lock.json
generated
710
package-lock.json
generated
@@ -1,8 +1,468 @@
|
||||
{
|
||||
"name": "bitwarden-mobile",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bitwarden-mobile",
|
||||
"version": "0.0.0",
|
||||
"devDependencies": {
|
||||
"gh-pages": "^3.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/array-union": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
|
||||
"integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"array-uniq": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/array-uniq": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
|
||||
"integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/async": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
|
||||
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.14"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/commondir": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/email-addresses": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz",
|
||||
"integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/filename-reserved-regex": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
|
||||
"integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/filenamify": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz",
|
||||
"integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"filename-reserved-regex": "^2.0.0",
|
||||
"strip-outer": "^1.0.1",
|
||||
"trim-repeated": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/find-cache-dir": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
|
||||
"integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"commondir": "^1.0.1",
|
||||
"make-dir": "^3.0.2",
|
||||
"pkg-dir": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/avajs/find-cache-dir?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/find-up": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6 <7 || >=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/gh-pages": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-3.2.3.tgz",
|
||||
"integrity": "sha512-jA1PbapQ1jqzacECfjUaO9gV8uBgU6XNMV0oXLtfCX3haGLe5Atq8BxlrADhbD6/UdG9j6tZLWAkAybndOXTJg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"async": "^2.6.1",
|
||||
"commander": "^2.18.0",
|
||||
"email-addresses": "^3.0.1",
|
||||
"filenamify": "^4.3.0",
|
||||
"find-cache-dir": "^3.3.1",
|
||||
"fs-extra": "^8.1.0",
|
||||
"globby": "^6.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"gh-pages": "bin/gh-pages.js",
|
||||
"gh-pages-clean": "bin/gh-pages-clean.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
||||
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/globby": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
|
||||
"integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"array-union": "^1.0.1",
|
||||
"glob": "^7.0.3",
|
||||
"object-assign": "^4.0.1",
|
||||
"pify": "^2.0.0",
|
||||
"pinkie-promise": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
|
||||
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/jsonfile": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
|
||||
"dev": true,
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"p-locate": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/make-dir": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
||||
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"semver": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/p-limit": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"p-try": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/p-locate": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"p-limit": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pify": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pinkie": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
|
||||
"integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pinkie-promise": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
|
||||
"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"pinkie": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-dir": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||
"integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"find-up": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-outer": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
|
||||
"integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"escape-string-regexp": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/trim-repeated": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
|
||||
"integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"escape-string-regexp": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"dev": true
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"array-union": {
|
||||
"version": "1.0.2",
|
||||
@@ -20,18 +480,18 @@
|
||||
"dev": true
|
||||
},
|
||||
"async": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz",
|
||||
"integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
|
||||
"integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "^4.17.10"
|
||||
"lodash": "^4.17.14"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
@@ -45,9 +505,15 @@
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.15.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
|
||||
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"commondir": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
@@ -56,6 +522,12 @@
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true
|
||||
},
|
||||
"email-addresses": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz",
|
||||
"integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==",
|
||||
"dev": true
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
@@ -63,39 +535,50 @@
|
||||
"dev": true
|
||||
},
|
||||
"filename-reserved-regex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz",
|
||||
"integrity": "sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q=",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
|
||||
"integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=",
|
||||
"dev": true
|
||||
},
|
||||
"filenamify": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz",
|
||||
"integrity": "sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=",
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz",
|
||||
"integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"filename-reserved-regex": "^1.0.0",
|
||||
"strip-outer": "^1.0.0",
|
||||
"filename-reserved-regex": "^2.0.0",
|
||||
"strip-outer": "^1.0.1",
|
||||
"trim-repeated": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"filenamify-url": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/filenamify-url/-/filenamify-url-1.0.0.tgz",
|
||||
"integrity": "sha1-syvYExnvWGO3MHi+1Q9GpPeXX1A=",
|
||||
"find-cache-dir": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
|
||||
"integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"filenamify": "^1.0.0",
|
||||
"humanize-url": "^1.0.0"
|
||||
"commondir": "^1.0.1",
|
||||
"make-dir": "^3.0.2",
|
||||
"pkg-dir": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"find-up": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
|
||||
"integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==",
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
}
|
||||
@@ -107,24 +590,24 @@
|
||||
"dev": true
|
||||
},
|
||||
"gh-pages": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-1.2.0.tgz",
|
||||
"integrity": "sha512-cGLYAvxtlQ1iTwAS4g7FreZPXoE/g62Fsxln2mmR19mgs4zZI+XJ+wVVUhBFCF/0+Nmvbq+abyTWue1m1BSnmg==",
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-3.2.3.tgz",
|
||||
"integrity": "sha512-jA1PbapQ1jqzacECfjUaO9gV8uBgU6XNMV0oXLtfCX3haGLe5Atq8BxlrADhbD6/UdG9j6tZLWAkAybndOXTJg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async": "2.6.1",
|
||||
"commander": "2.15.1",
|
||||
"filenamify-url": "^1.0.0",
|
||||
"fs-extra": "^5.0.0",
|
||||
"globby": "^6.1.0",
|
||||
"graceful-fs": "4.1.11",
|
||||
"rimraf": "^2.6.2"
|
||||
"async": "^2.6.1",
|
||||
"commander": "^2.18.0",
|
||||
"email-addresses": "^3.0.1",
|
||||
"filenamify": "^4.3.0",
|
||||
"find-cache-dir": "^3.3.1",
|
||||
"fs-extra": "^8.1.0",
|
||||
"globby": "^6.1.0"
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
|
||||
"integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
||||
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
@@ -149,21 +632,11 @@
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
||||
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
|
||||
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
|
||||
"dev": true
|
||||
},
|
||||
"humanize-url": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/humanize-url/-/humanize-url-1.0.1.tgz",
|
||||
"integrity": "sha1-9KuZ4NKIF0yk4eUEB8VfuuRk7/8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"normalize-url": "^1.0.0",
|
||||
"strip-url-auth": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
@@ -175,15 +648,9 @@
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
||||
"dev": true
|
||||
},
|
||||
"is-plain-obj": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
|
||||
"integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"jsonfile": {
|
||||
@@ -195,12 +662,30 @@
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-locate": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"make-dir": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
||||
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"semver": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
@@ -210,18 +695,6 @@
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"normalize-url": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz",
|
||||
"integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"object-assign": "^4.0.1",
|
||||
"prepend-http": "^1.0.0",
|
||||
"query-string": "^4.1.0",
|
||||
"sort-keys": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
@@ -237,6 +710,36 @@
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-try": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-limit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"dev": true
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||
"dev": true
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
@@ -264,44 +767,19 @@
|
||||
"pinkie": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"prepend-http": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
|
||||
"integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
|
||||
"dev": true
|
||||
},
|
||||
"query-string": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
|
||||
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
|
||||
"pkg-dir": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||
"integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"object-assign": "^4.1.0",
|
||||
"strict-uri-encode": "^1.0.0"
|
||||
"find-up": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
|
||||
"integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"sort-keys": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
|
||||
"integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-plain-obj": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"strict-uri-encode": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
|
||||
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
},
|
||||
"strip-outer": {
|
||||
@@ -313,12 +791,6 @@
|
||||
"escape-string-regexp": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"strip-url-auth": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-url-auth/-/strip-url-auth-1.0.1.tgz",
|
||||
"integrity": "sha1-IrD6OkE4WzO+PzMVUbu4N/oM164=",
|
||||
"dev": true
|
||||
},
|
||||
"trim-repeated": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
"clean:l10n": "git push origin --delete l10n_master"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gh-pages": "^1.2.0"
|
||||
"gh-pages": "^3.2.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace Bit.Droid.Accessibility
|
||||
// So keep them in sync with:
|
||||
// - AutofillHelpers.{TrustedBrowsers,CompatBrowsers}
|
||||
// - Resources/xml/autofillservice.xml
|
||||
new Browser("alook.browser", "search_fragment_input_view"),
|
||||
new Browser("com.amazon.cloud9", "url"),
|
||||
new Browser("com.android.browser", "url"),
|
||||
new Browser("com.android.chrome", "url_bar"),
|
||||
@@ -52,6 +51,7 @@ namespace Bit.Droid.Accessibility
|
||||
new Browser("com.ecosia.android", "url_bar"),
|
||||
new Browser("com.google.android.apps.chrome", "url_bar"),
|
||||
new Browser("com.google.android.apps.chrome_dev", "url_bar"),
|
||||
// Rem. for "com.google.android.captiveportallogin": URL displayed in ActionBar subtitle without viewId.
|
||||
new Browser("com.jamal2367.styx", "search"),
|
||||
new Browser("com.kiwibrowser.browser", "url_bar"),
|
||||
new Browser("com.microsoft.emmx", "url_bar"),
|
||||
|
||||
@@ -49,7 +49,6 @@ namespace Bit.Droid.Autofill
|
||||
// - ... to keep this list in sync with values in AccessibilityHelpers.SupportedBrowsers [Section A], too.
|
||||
public static HashSet<string> CompatBrowsers = new HashSet<string>
|
||||
{
|
||||
"alook.browser",
|
||||
"com.amazon.cloud9",
|
||||
"com.android.browser",
|
||||
"com.android.chrome",
|
||||
@@ -69,6 +68,7 @@ namespace Bit.Droid.Autofill
|
||||
"com.ecosia.android",
|
||||
"com.google.android.apps.chrome",
|
||||
"com.google.android.apps.chrome_dev",
|
||||
"com.google.android.captiveportallogin",
|
||||
"com.jamal2367.styx",
|
||||
"com.kiwibrowser.browser",
|
||||
"com.microsoft.emmx",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:versionCode="1"
|
||||
android:versionName="2.14.2"
|
||||
android:versionName="2.14.3"
|
||||
android:installLocation="internalOnly"
|
||||
package="com.x8bit.bitwarden">
|
||||
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
-->
|
||||
<autofill-service xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:supportsInlineSuggestions="true">
|
||||
<compatibility-package
|
||||
android:name="alook.browser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.amazon.cloud9"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
@@ -71,6 +68,9 @@
|
||||
<compatibility-package
|
||||
android:name="com.google.android.apps.chrome_dev"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.google.android.captiveportallogin"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="com.jamal2367.styx"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
@@ -211,10 +211,10 @@
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
<compatibility-package
|
||||
android:name="org.mozilla.firefox"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
android:maxLongVersionCode="2015836711"/>
|
||||
<compatibility-package
|
||||
android:name="org.mozilla.firefox_beta"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
android:maxLongVersionCode="2015849447"/>
|
||||
<compatibility-package
|
||||
android:name="org.mozilla.reference.browser"
|
||||
android:maxLongVersionCode="10000000000"/>
|
||||
|
||||
@@ -98,5 +98,15 @@ namespace Bit.Droid.Services
|
||||
Console.WriteLine(".NET Fallback Language/Locale:" + netLanguage + " (application-specific)");
|
||||
return netLanguage;
|
||||
}
|
||||
|
||||
public string GetLocaleShortDate(DateTime? date)
|
||||
{
|
||||
return date?.ToShortDateString() ?? string.Empty;
|
||||
}
|
||||
|
||||
public string GetLocaleShortTime(DateTime? time)
|
||||
{
|
||||
return time?.ToShortTimeString() ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,22 @@
|
||||
using System.Globalization;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ILocalizeService
|
||||
{
|
||||
CultureInfo GetCurrentCultureInfo();
|
||||
|
||||
/// <summary>
|
||||
/// Format date using device locale.
|
||||
/// Needed for iOS as it provides locales unsupported in .Net
|
||||
/// </summary>
|
||||
string GetLocaleShortDate(DateTime? date);
|
||||
|
||||
/// <summary>
|
||||
/// Format time using device locale.
|
||||
/// Needed for iOS as it provides locales unsupported in .Net
|
||||
/// </summary>
|
||||
string GetLocaleShortTime(DateTime? time);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Resources\" />
|
||||
<Folder Include="Behaviors\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -411,4 +412,7 @@
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Behaviors\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
using Xamarin.Essentials;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Behaviors
|
||||
{
|
||||
/// <summary>
|
||||
/// This behavior prevents the Editor to be automatically scrolled to the bottom on focus.
|
||||
/// This is needed due to this Xamarin Forms issue: https://github.com/xamarin/Xamarin.Forms/issues/2233
|
||||
/// </summary>
|
||||
public class EditorPreventAutoBottomScrollingOnFocusedBehavior : Behavior<Editor>
|
||||
{
|
||||
public static readonly BindableProperty ParentScrollViewProperty
|
||||
= BindableProperty.Create(nameof(ParentScrollView), typeof(ScrollView), typeof(EditorPreventAutoBottomScrollingOnFocusedBehavior));
|
||||
|
||||
public ScrollView ParentScrollView
|
||||
{
|
||||
get => (ScrollView)GetValue(ParentScrollViewProperty);
|
||||
set => SetValue(ParentScrollViewProperty, value);
|
||||
}
|
||||
|
||||
protected override void OnAttachedTo(Editor bindable)
|
||||
{
|
||||
base.OnAttachedTo(bindable);
|
||||
|
||||
bindable.Focused += OnFocused;
|
||||
}
|
||||
|
||||
private void OnFocused(object sender, FocusEventArgs e)
|
||||
{
|
||||
if (DeviceInfo.Platform.Equals(DevicePlatform.iOS) && ParentScrollView != null)
|
||||
{
|
||||
ParentScrollView.ScrollToAsync(ParentScrollView.ScrollX, ParentScrollView.ScrollY, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDetachingFrom(Editor bindable)
|
||||
{
|
||||
bindable.Focused -= OnFocused;
|
||||
|
||||
base.OnDetachingFrom(bindable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@
|
||||
WidthRequest="22"
|
||||
HeightRequest="22"
|
||||
IsVisible="{Binding ShowIconImage}"
|
||||
Source="{Binding Cipher, Converter={StaticResource iconImageConverter}}"
|
||||
Source="{Binding IconImageSource, Mode=OneTime}"
|
||||
AutomationProperties.IsInAccessibleTree="False" />
|
||||
|
||||
<Grid RowSpacing="0" ColumnSpacing="0" Grid.Row="0" Grid.Column="1" VerticalOptions="Center" Padding="0, 7">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Bit.Core.Models.View;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.Core.Models.View;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
@@ -7,6 +8,7 @@ namespace Bit.App.Controls
|
||||
{
|
||||
private CipherView _cipher;
|
||||
private bool _websiteIconsEnabled;
|
||||
private string _iconImageSource = string.Empty;
|
||||
|
||||
public CipherViewCellViewModel(CipherView cipherView, bool websiteIconsEnabled)
|
||||
{
|
||||
@@ -28,8 +30,22 @@ namespace Bit.App.Controls
|
||||
|
||||
public bool ShowIconImage
|
||||
{
|
||||
get => WebsiteIconsEnabled && !string.IsNullOrWhiteSpace(Cipher.Login?.Uri) &&
|
||||
Cipher.Login.Uri.StartsWith("http");
|
||||
get => WebsiteIconsEnabled
|
||||
&& !string.IsNullOrWhiteSpace(Cipher.Login?.Uri)
|
||||
&& IconImageSource != null;
|
||||
}
|
||||
|
||||
public string IconImageSource
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_iconImageSource == string.Empty) // default value since icon source can return null
|
||||
{
|
||||
_iconImageSource = IconImageHelper.GetLoginIconImage(Cipher);
|
||||
}
|
||||
return _iconImageSource;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
25
src/App/Effects/ScrollEnabledEffect.cs
Normal file
25
src/App/Effects/ScrollEnabledEffect.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Effects
|
||||
{
|
||||
public class ScrollEnabledEffect : RoutingEffect
|
||||
{
|
||||
public static readonly BindableProperty IsScrollEnabledProperty =
|
||||
BindableProperty.CreateAttached("IsScrollEnabled", typeof(bool), typeof(ScrollEnabledEffect), true);
|
||||
|
||||
public static bool GetIsScrollEnabled(BindableObject view)
|
||||
{
|
||||
return (bool)view.GetValue(IsScrollEnabledProperty);
|
||||
}
|
||||
|
||||
public static void SetIsScrollEnabled(BindableObject view, bool value)
|
||||
{
|
||||
view.SetValue(IsScrollEnabledProperty, value);
|
||||
}
|
||||
|
||||
public ScrollEnabledEffect()
|
||||
: base("Bitwarden.ScrollEnabledEffect")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,8 +68,7 @@
|
||||
<controls:MonoLabel LineBreakMode="CharacterWrap"
|
||||
Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
StyleClass="list-title, list-title-platform"
|
||||
TextType="Html"
|
||||
StyleClass="list-title, list-title-platform, text-html"
|
||||
Text="{Binding Password, Mode=OneWay, Converter={StaticResource coloredPassword}}" />
|
||||
<Label LineBreakMode="TailTruncation"
|
||||
Grid.Column="0"
|
||||
|
||||
@@ -63,10 +63,9 @@
|
||||
</Frame>
|
||||
</Grid>
|
||||
<controls:MonoLabel
|
||||
StyleClass="text-lg, text-html"
|
||||
Text="{Binding ColoredPassword, Mode=OneWay}"
|
||||
TextType="Html"
|
||||
Margin="0, 20"
|
||||
StyleClass="text-lg"
|
||||
HorizontalTextAlignment="Center"
|
||||
HorizontalOptions="CenterAndExpand"
|
||||
LineBreakMode="CharacterWrap" />
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
xmlns:behaviors="clr-namespace:Bit.App.Behaviors"
|
||||
xmlns:effects="clr-namespace:Bit.App.Effects"
|
||||
x:DataType="pages:SendAddEditPageViewModel"
|
||||
x:Name="_page"
|
||||
Title="{Binding PageTitle}">
|
||||
@@ -201,7 +203,15 @@
|
||||
Text="{Binding Send.Text.Text}"
|
||||
IsEnabled="{Binding SendEnabled}"
|
||||
StyleClass="box-value"
|
||||
Margin="{Binding EditorMargins}" />
|
||||
Margin="{Binding EditorMargins}"
|
||||
effects:ScrollEnabledEffect.IsScrollEnabled="false" >
|
||||
<Editor.Behaviors>
|
||||
<behaviors:EditorPreventAutoBottomScrollingOnFocusedBehavior ParentScrollView="{x:Reference _scrollView}" />
|
||||
</Editor.Behaviors>
|
||||
<Editor.Effects>
|
||||
<effects:ScrollEnabledEffect />
|
||||
</Editor.Effects>
|
||||
</Editor>
|
||||
<BoxView
|
||||
StyleClass="box-row-separator"
|
||||
IsVisible="{Binding ShowEditorSeparators}" />
|
||||
@@ -443,7 +453,15 @@
|
||||
Text="{Binding Send.Notes}"
|
||||
IsEnabled="{Binding SendEnabled}"
|
||||
StyleClass="box-value"
|
||||
Margin="{Binding EditorMargins}" />
|
||||
Margin="{Binding EditorMargins}"
|
||||
effects:ScrollEnabledEffect.IsScrollEnabled="false" >
|
||||
<Editor.Behaviors>
|
||||
<behaviors:EditorPreventAutoBottomScrollingOnFocusedBehavior ParentScrollView="{x:Reference _scrollView}" />
|
||||
</Editor.Behaviors>
|
||||
<Editor.Effects>
|
||||
<effects:ScrollEnabledEffect />
|
||||
</Editor.Effects>
|
||||
</Editor>
|
||||
<BoxView
|
||||
StyleClass="box-row-separator"
|
||||
IsVisible="{Binding ShowEditorSeparators}" />
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<u:DateTimeConverter x:Key="dateTime" />
|
||||
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
|
||||
x:Name="_closeItem" x:Key="closeItem" />
|
||||
<StackLayout
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace Bit.App.Pages
|
||||
private readonly ISyncService _syncService;
|
||||
private readonly IBiometricService _biometricService;
|
||||
private readonly IPolicyService _policyService;
|
||||
private readonly ILocalizeService _localizeService;
|
||||
|
||||
private const int CustomVaultTimeoutValue = -100;
|
||||
|
||||
@@ -72,6 +73,7 @@ namespace Bit.App.Pages
|
||||
_syncService = ServiceContainer.Resolve<ISyncService>("syncService");
|
||||
_biometricService = ServiceContainer.Resolve<IBiometricService>("biometricService");
|
||||
_policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
|
||||
_localizeService = ServiceContainer.Resolve<ILocalizeService>("localizeService");
|
||||
|
||||
GroupedItems = new ExtendedObservableCollection<SettingsPageListGroup>();
|
||||
PageTitle = AppResources.Settings;
|
||||
@@ -86,8 +88,9 @@ namespace Bit.App.Pages
|
||||
if (lastSync != null)
|
||||
{
|
||||
lastSync = lastSync.Value.ToLocalTime();
|
||||
_lastSyncDate = string.Format("{0} {1}", lastSync.Value.ToShortDateString(),
|
||||
lastSync.Value.ToShortTimeString());
|
||||
_lastSyncDate = string.Format("{0} {1}",
|
||||
_localizeService.GetLocaleShortDate(lastSync.Value),
|
||||
_localizeService.GetLocaleShortTime(lastSync.Value));
|
||||
}
|
||||
|
||||
if (await _policyService.PolicyAppliesToUser(PolicyType.MaximumVaultTimeout))
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Bit.App.Pages
|
||||
private readonly IPlatformUtilsService _platformUtilsService;
|
||||
private readonly IStorageService _storageService;
|
||||
private readonly ISyncService _syncService;
|
||||
private readonly ILocalizeService _localizeService;
|
||||
|
||||
private string _lastSync = "--";
|
||||
private bool _inited;
|
||||
@@ -25,6 +26,7 @@ namespace Bit.App.Pages
|
||||
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
||||
_storageService = ServiceContainer.Resolve<IStorageService>("storageService");
|
||||
_syncService = ServiceContainer.Resolve<ISyncService>("syncService");
|
||||
_localizeService = ServiceContainer.Resolve<ILocalizeService>("localizeService");
|
||||
|
||||
PageTitle = AppResources.Sync;
|
||||
}
|
||||
@@ -68,7 +70,9 @@ namespace Bit.App.Pages
|
||||
if (last != null)
|
||||
{
|
||||
var localDate = last.Value.ToLocalTime();
|
||||
LastSync = string.Format("{0} {1}", localDate.ToShortDateString(), localDate.ToShortTimeString());
|
||||
LastSync = string.Format("{0} {1}",
|
||||
_localizeService.GetLocaleShortDate(localDate),
|
||||
_localizeService.GetLocaleShortTime(localDate));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
xmlns:views="clr-namespace:Bit.Core.Models.View;assembly=BitwardenCore"
|
||||
xmlns:behaviors="clr-namespace:Bit.App.Behaviors"
|
||||
xmlns:effects="clr-namespace:Bit.App.Effects"
|
||||
x:DataType="pages:AddEditPageViewModel"
|
||||
x:Name="_page"
|
||||
Title="{Binding PageTitle}">
|
||||
@@ -583,8 +585,16 @@
|
||||
<Editor
|
||||
x:Name="_notesEditor"
|
||||
AutoSize="TextChanges"
|
||||
Text="{Binding Cipher.Notes}"
|
||||
StyleClass="box-value" />
|
||||
StyleClass="box-value"
|
||||
effects:ScrollEnabledEffect.IsScrollEnabled="false"
|
||||
Text="{Binding Cipher.Notes}">
|
||||
<Editor.Behaviors>
|
||||
<behaviors:EditorPreventAutoBottomScrollingOnFocusedBehavior ParentScrollView="{x:Reference _scrollView}" />
|
||||
</Editor.Behaviors>
|
||||
<Editor.Effects>
|
||||
<effects:ScrollEnabledEffect />
|
||||
</Editor.Effects>
|
||||
</Editor>
|
||||
</StackLayout>
|
||||
<BoxView StyleClass="box-row-separator" IsVisible="{Binding ShowNotesSeparator}" />
|
||||
</StackLayout>
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<u:DateTimeConverter x:Key="dateTime" />
|
||||
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
|
||||
x:Name="_closeItem" x:Key="closeItem" />
|
||||
<StackLayout
|
||||
|
||||
@@ -59,8 +59,7 @@
|
||||
<controls:MonoLabel LineBreakMode="CharacterWrap"
|
||||
Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
StyleClass="list-title, list-title-platform"
|
||||
TextType="Html"
|
||||
StyleClass="list-title, list-title-platform, text-html"
|
||||
Text="{Binding Password, Mode=OneWay, Converter={StaticResource coloredPassword}}" />
|
||||
<Label LineBreakMode="TailTruncation"
|
||||
Grid.Column="0"
|
||||
|
||||
@@ -120,8 +120,7 @@
|
||||
IsVisible="{Binding ShowPassword, Converter={StaticResource inverseBool}}" />
|
||||
<controls:MonoLabel
|
||||
Text="{Binding ColoredPassword, Mode=OneWay}"
|
||||
TextType="Html"
|
||||
StyleClass="box-value"
|
||||
StyleClass="box-value, text-html"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
LineBreakMode="CharacterWrap"
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace Bit.App.Pages
|
||||
private readonly IMessagingService _messagingService;
|
||||
private readonly IEventService _eventService;
|
||||
private readonly IPasswordRepromptService _passwordRepromptService;
|
||||
private readonly ILocalizeService _localizeService;
|
||||
private CipherView _cipher;
|
||||
private List<ViewPageFieldViewModel> _fields;
|
||||
private bool _canAccessPremium;
|
||||
@@ -52,6 +53,7 @@ namespace Bit.App.Pages
|
||||
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
||||
_eventService = ServiceContainer.Resolve<IEventService>("eventService");
|
||||
_passwordRepromptService = ServiceContainer.Resolve<IPasswordRepromptService>("passwordRepromptService");
|
||||
_localizeService = ServiceContainer.Resolve<ILocalizeService>("localizeService");
|
||||
CopyCommand = new Command<string>((id) => CopyAsync(id, null));
|
||||
CopyUriCommand = new Command<LoginUriView>(CopyUri);
|
||||
CopyFieldCommand = new Command<FieldView>(CopyField);
|
||||
@@ -152,8 +154,8 @@ namespace Bit.App.Pages
|
||||
fs.Spans.Add(new Span
|
||||
{
|
||||
Text = string.Format(" {0} {1}",
|
||||
Cipher.RevisionDate.ToLocalTime().ToShortDateString(),
|
||||
Cipher.RevisionDate.ToLocalTime().ToShortTimeString())
|
||||
_localizeService.GetLocaleShortDate(Cipher.RevisionDate.ToLocalTime()),
|
||||
_localizeService.GetLocaleShortTime(Cipher.RevisionDate.ToLocalTime()))
|
||||
});
|
||||
return fs;
|
||||
}
|
||||
@@ -171,8 +173,8 @@ namespace Bit.App.Pages
|
||||
fs.Spans.Add(new Span
|
||||
{
|
||||
Text = string.Format(" {0} {1}",
|
||||
Cipher.PasswordRevisionDisplayDate?.ToLocalTime().ToShortDateString(),
|
||||
Cipher.PasswordRevisionDisplayDate?.ToLocalTime().ToShortTimeString())
|
||||
_localizeService.GetLocaleShortDate(Cipher.PasswordRevisionDisplayDate?.ToLocalTime()),
|
||||
_localizeService.GetLocaleShortTime(Cipher.PasswordRevisionDisplayDate?.ToLocalTime()))
|
||||
});
|
||||
return fs;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,14 @@
|
||||
<Setter Property="FontAttributes"
|
||||
Value="Bold" />
|
||||
</Style>
|
||||
<Style TargetType="Label"
|
||||
Class="text-html"
|
||||
ApplyToDerivedTypes="True">
|
||||
<Setter Property="TextColor"
|
||||
Value="Default" />
|
||||
<Setter Property="TextType"
|
||||
Value="Html" />
|
||||
</Style>
|
||||
|
||||
<!-- Pages -->
|
||||
<Style TargetType="TabbedPage"
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
using System;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Utilities
|
||||
{
|
||||
public class DateTimeConverter : IValueConverter
|
||||
{
|
||||
private readonly ILocalizeService _localizeService;
|
||||
|
||||
public DateTimeConverter()
|
||||
{
|
||||
_localizeService = ServiceContainer.Resolve<ILocalizeService>("localizeService");
|
||||
}
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter,
|
||||
System.Globalization.CultureInfo culture)
|
||||
{
|
||||
@@ -17,7 +26,9 @@ namespace Bit.App.Utilities
|
||||
return string.Empty;
|
||||
}
|
||||
var d = ((DateTime)value).ToLocalTime();
|
||||
return string.Format("{0} {1}", d.ToShortDateString(), d.ToShortTimeString());
|
||||
return string.Format("{0} {1}",
|
||||
_localizeService.GetLocaleShortDate(d),
|
||||
_localizeService.GetLocaleShortTime(d));
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter,
|
||||
|
||||
@@ -10,8 +10,6 @@ namespace Bit.App.Utilities
|
||||
{
|
||||
public class IconImageConverter : IValueConverter
|
||||
{
|
||||
private readonly IEnvironmentService _environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var cipher = value as CipherView;
|
||||
@@ -29,51 +27,65 @@ namespace Bit.App.Utilities
|
||||
switch (cipher.Type)
|
||||
{
|
||||
case CipherType.Login:
|
||||
icon = GetLoginIconImage(cipher);
|
||||
icon = IconImageHelper.GetLoginIconImage(cipher);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
|
||||
string GetLoginIconImage(CipherView cipher)
|
||||
public static class IconImageHelper
|
||||
{
|
||||
public static string GetLoginIconImage(CipherView cipher)
|
||||
{
|
||||
string image = null;
|
||||
if (cipher.Login.Uri != null)
|
||||
if (cipher.Login.HasUris)
|
||||
{
|
||||
var hostnameUri = cipher.Login.Uri;
|
||||
var isWebsite = false;
|
||||
|
||||
if (!hostnameUri.Contains("://") && hostnameUri.Contains("."))
|
||||
foreach (var uri in cipher.Login.Uris)
|
||||
{
|
||||
hostnameUri = string.Concat("http://", hostnameUri);
|
||||
isWebsite = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
isWebsite = hostnameUri.StartsWith("http") && hostnameUri.Contains(".");
|
||||
}
|
||||
|
||||
if (isWebsite)
|
||||
{
|
||||
var hostname = CoreHelpers.GetHostname(hostnameUri);
|
||||
var iconsUrl = _environmentService.IconsUrl;
|
||||
if (string.IsNullOrWhiteSpace(iconsUrl))
|
||||
var hostnameUri = uri.Uri;
|
||||
var isWebsite = false;
|
||||
if (!hostnameUri.Contains("."))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(_environmentService.BaseUrl))
|
||||
{
|
||||
iconsUrl = string.Format("{0}/icons", _environmentService.BaseUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
iconsUrl = "https://icons.bitwarden.net";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!hostnameUri.Contains("://"))
|
||||
{
|
||||
hostnameUri = string.Concat("http://", hostnameUri);
|
||||
}
|
||||
isWebsite = hostnameUri.StartsWith("http");
|
||||
|
||||
if (isWebsite)
|
||||
{
|
||||
image = GetIconUrl(hostnameUri);
|
||||
break;
|
||||
}
|
||||
image = string.Format("{0}/{1}/icon.png", iconsUrl, hostname);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
private static string GetIconUrl(string hostnameUri)
|
||||
{
|
||||
IEnvironmentService _environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
||||
|
||||
var hostname = CoreHelpers.GetHostname(hostnameUri);
|
||||
var iconsUrl = _environmentService.IconsUrl;
|
||||
if (string.IsNullOrWhiteSpace(iconsUrl))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(_environmentService.BaseUrl))
|
||||
{
|
||||
iconsUrl = string.Format("{0}/icons", _environmentService.BaseUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
iconsUrl = "https://icons.bitwarden.net";
|
||||
}
|
||||
}
|
||||
return string.Format("{0}/{1}/icon.png", iconsUrl, hostname);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.8bit.bitwarden.autofill</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.14.2</string>
|
||||
<string>2.14.3</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CFBundleLocalizations</key>
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Bit.iOS.Core.Controllers
|
||||
public abstract Action Cancel { get; }
|
||||
|
||||
public FormEntryTableViewCell MasterPasswordCell { get; set; } = new FormEntryTableViewCell(
|
||||
AppResources.MasterPassword);
|
||||
AppResources.MasterPassword, useButton: true);
|
||||
|
||||
public string BiometricIntegrityKey { get; set; }
|
||||
|
||||
@@ -95,6 +95,12 @@ namespace Bit.iOS.Core.Controllers
|
||||
{
|
||||
MasterPasswordCell.TextField.KeyboardType = UIKeyboardType.NumberPad;
|
||||
}
|
||||
MasterPasswordCell.Button.TitleLabel.Font = UIFont.FromName("FontAwesome", 28f);
|
||||
MasterPasswordCell.Button.SetTitle("\uf06e", UIControlState.Normal);
|
||||
MasterPasswordCell.Button.TouchUpInside += (sender, e) => {
|
||||
MasterPasswordCell.TextField.SecureTextEntry = !MasterPasswordCell.TextField.SecureTextEntry;
|
||||
MasterPasswordCell.Button.SetTitle(MasterPasswordCell.TextField.SecureTextEntry ? "\uf06e" : "\uf070", UIControlState.Normal);
|
||||
};
|
||||
|
||||
TableView.RowHeight = UITableView.AutomaticDimension;
|
||||
TableView.EstimatedRowHeight = 70;
|
||||
|
||||
25
src/iOS.Core/Effects/ScrollEnabledEffect.cs
Normal file
25
src/iOS.Core/Effects/ScrollEnabledEffect.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Bit.iOS.Core.Effects;
|
||||
using UIKit;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Platform.iOS;
|
||||
|
||||
[assembly: ResolutionGroupName("Bitwarden")]
|
||||
[assembly: ExportEffect(typeof(ScrollEnabledEffect), "ScrollEnabledEffect")]
|
||||
namespace Bit.iOS.Core.Effects
|
||||
{
|
||||
public class ScrollEnabledEffect : PlatformEffect
|
||||
{
|
||||
protected override void OnAttached()
|
||||
{
|
||||
// this can be for any view that inherits from UIScrollView like UITextView.
|
||||
if (Element != null && Control is UIScrollView scrollView)
|
||||
{
|
||||
scrollView.ScrollEnabled = App.Effects.ScrollEnabledEffect.GetIsScrollEnabled(Element);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDetached()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,5 +100,25 @@ namespace Bit.iOS.Core.Services
|
||||
Console.WriteLine(".NET Fallback Language/Locale:" + netLanguage + " (application-specific)");
|
||||
return netLanguage;
|
||||
}
|
||||
|
||||
public string GetLocaleShortDate(DateTime? date)
|
||||
{
|
||||
using (var df = new NSDateFormatter())
|
||||
{
|
||||
df.Locale = NSLocale.CurrentLocale;
|
||||
df.DateStyle = NSDateFormatterStyle.Short;
|
||||
return df.StringFor((NSDate)date);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetLocaleShortTime(DateTime? time)
|
||||
{
|
||||
using (var df = new NSDateFormatter())
|
||||
{
|
||||
df.Locale = NSLocale.CurrentLocale;
|
||||
df.TimeStyle = NSDateFormatterStyle.Short;
|
||||
return df.StringFor((NSDate)time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,25 @@
|
||||
using Bit.iOS.Core.Controllers;
|
||||
using Bit.iOS.Core.Utilities;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using UIKit;
|
||||
|
||||
namespace Bit.iOS.Core.Views
|
||||
{
|
||||
public class FormEntryTableViewCell : ExtendedUITableViewCell, ISelectable
|
||||
{
|
||||
public UILabel Label { get; set; }
|
||||
public UITextField TextField { get; set; }
|
||||
public UITextView TextView { get; set; }
|
||||
public UIButton Button { get; set; }
|
||||
public event EventHandler ValueChanged;
|
||||
|
||||
|
||||
public FormEntryTableViewCell(
|
||||
string labelName = null,
|
||||
bool useTextView = false,
|
||||
nfloat? height = null,
|
||||
bool useButton = false,
|
||||
bool useLabelAsPlaceholder = false,
|
||||
float leadingConstant = 15f)
|
||||
: base(UITableViewCellStyle.Default, nameof(FormEntryTableViewCell))
|
||||
@@ -103,7 +112,7 @@ namespace Bit.iOS.Core.Views
|
||||
ContentView.Add(TextField);
|
||||
ContentView.AddConstraints(new NSLayoutConstraint[] {
|
||||
NSLayoutConstraint.Create(TextField, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.Leading, 1f, leadingConstant),
|
||||
NSLayoutConstraint.Create(ContentView, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, TextField, NSLayoutAttribute.Trailing, 1f, 15f),
|
||||
NSLayoutConstraint.Create(ContentView, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, TextField, NSLayoutAttribute.Trailing, 1f, useButton ? 55f : 15f),
|
||||
NSLayoutConstraint.Create(ContentView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, TextField, NSLayoutAttribute.Bottom, 1f, 10f)
|
||||
});
|
||||
|
||||
@@ -138,12 +147,21 @@ namespace Bit.iOS.Core.Views
|
||||
NSLayoutConstraint.Create(ContentView, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, Label, NSLayoutAttribute.Trailing, 1f, 15f)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public UILabel Label { get; set; }
|
||||
public UITextField TextField { get; set; }
|
||||
public UITextView TextView { get; set; }
|
||||
public event EventHandler ValueChanged;
|
||||
if (useButton)
|
||||
{
|
||||
Button = new UIButton(UIButtonType.System);
|
||||
Button.Frame = ContentView.Bounds;
|
||||
Button.TranslatesAutoresizingMaskIntoConstraints = false;
|
||||
Button.SetTitleColor(ThemeHelpers.PrimaryColor, UIControlState.Normal);
|
||||
|
||||
ContentView.Add(Button);
|
||||
|
||||
ContentView.BottomAnchor.ConstraintEqualTo(Button.BottomAnchor, 10f).Active = true;
|
||||
ContentView.TrailingAnchor.ConstraintEqualTo(Button.TrailingAnchor, 10f).Active = true;
|
||||
Button.LeadingAnchor.ConstraintEqualTo(TextField.TrailingAnchor, 10f).Active = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Select()
|
||||
{
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Resources\" />
|
||||
<Folder Include="Effects\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Constants.cs" />
|
||||
@@ -189,6 +190,7 @@
|
||||
<Compile Include="Views\SwitchTableViewCell.cs" />
|
||||
<Compile Include="Views\Toast.cs" />
|
||||
<Compile Include="Renderers\SelectableLabelRenderer.cs" />
|
||||
<Compile Include="Effects\ScrollEnabledEffect.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\App\App.csproj">
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.8bit.bitwarden.find-login-action-extension</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.14.2</string>
|
||||
<string>2.14.3</string>
|
||||
<key>CFBundleLocalizations</key>
|
||||
<array>
|
||||
<string>en</string>
|
||||
|
||||
73
src/iOS.Safari/ActionViewController.cs
Normal file
73
src/iOS.Safari/ActionViewController.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
|
||||
using MobileCoreServices;
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
|
||||
namespace iOS.Safari
|
||||
{
|
||||
public partial class ActionViewController : UIViewController
|
||||
{
|
||||
protected ActionViewController(IntPtr handle) : base(handle)
|
||||
{
|
||||
// Note: this .ctor should not contain any initialization logic.
|
||||
}
|
||||
|
||||
public override void DidReceiveMemoryWarning()
|
||||
{
|
||||
// Releases the view if it doesn't have a superview.
|
||||
base.DidReceiveMemoryWarning();
|
||||
|
||||
// Release any cached data, images, etc that aren't in use.
|
||||
}
|
||||
|
||||
public override void ViewDidLoad()
|
||||
{
|
||||
base.ViewDidLoad();
|
||||
|
||||
// Get the item[s] we're handling from the extension context.
|
||||
|
||||
// For example, look for an image and place it into an image view.
|
||||
// Replace this with something appropriate for the type[s] your extension supports.
|
||||
bool imageFound = false;
|
||||
|
||||
foreach (var item in ExtensionContext.InputItems)
|
||||
{
|
||||
foreach (var itemProvider in item.Attachments)
|
||||
{
|
||||
if (itemProvider.HasItemConformingTo(UTType.Image))
|
||||
{
|
||||
// This is an image. We'll load it, then place it in our image view.
|
||||
itemProvider.LoadItem(UTType.Image, null, delegate (NSObject image, NSError error)
|
||||
{
|
||||
var url = image as NSUrl;
|
||||
if (url != null)
|
||||
{
|
||||
NSOperationQueue.MainQueue.AddOperation(delegate
|
||||
{
|
||||
imageView.Image = UIImage.LoadFromData(NSData.FromUrl(url));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
imageFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (imageFound)
|
||||
{
|
||||
// We only handle one image, so stop looking for more.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partial void DoneClicked(NSObject sender)
|
||||
{
|
||||
// Return any edited content to the host app.
|
||||
// This template doesn't do anything, so we just echo the passed-in items.
|
||||
ExtensionContext.CompleteRequest(ExtensionContext.InputItems, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
24
src/iOS.Safari/ActionViewController.designer.cs
generated
Normal file
24
src/iOS.Safari/ActionViewController.designer.cs
generated
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// This file has been generated automatically by MonoDevelop to store outlets and
|
||||
// actions made in the Xcode designer. If it is removed, they will be lost.
|
||||
// Manual changes to this file may not be handled correctly.
|
||||
//
|
||||
using Foundation;
|
||||
|
||||
namespace iOS.Safari
|
||||
{
|
||||
[Register("ActionViewController")]
|
||||
partial class ActionViewController
|
||||
{
|
||||
[Outlet]
|
||||
UIKit.UIImageView imageView { get; set; }
|
||||
|
||||
[Action("DoneClicked:")]
|
||||
partial void DoneClicked(Foundation.NSObject sender);
|
||||
|
||||
void ReleaseDesignerOutlets()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
6
src/iOS.Safari/Entitlements.plist
Normal file
6
src/iOS.Safari/Entitlements.plist
Normal file
@@ -0,0 +1,6 @@
|
||||
<?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>
|
||||
</dict>
|
||||
</plist>
|
||||
31
src/iOS.Safari/Info.plist
Normal file
31
src/iOS.Safari/Info.plist
Normal file
@@ -0,0 +1,31 @@
|
||||
<?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>CFBundleDisplayName</key>
|
||||
<string>iOS.Safari</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>iOS.Safari</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.8bit.bitwarden.iOS-Safari</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.14.3</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>15.0</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.Safari.web-extension</string>
|
||||
<key>NSExtensionPrincipalClass</key>
|
||||
<string>SafariWebExtensionHandler</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
1817
src/iOS.Safari/Resources/_locales/az/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/az/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/be/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/be/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/bg/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/bg/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/bn/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/bn/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/ca/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/ca/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/cs/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/cs/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/da/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/da/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/de/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/de/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/el/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/el/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1825
src/iOS.Safari/Resources/_locales/en/messages.json
Normal file
1825
src/iOS.Safari/Resources/_locales/en/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/en_GB/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/en_GB/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/en_IN/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/en_IN/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/es/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/es/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/et/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/et/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/fa/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/fa/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/fi/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/fi/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/fil/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/fil/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/fr/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/fr/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/he/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/he/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/hi/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/hi/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/hr/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/hr/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/hu/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/hu/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/id/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/id/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/it/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/it/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/ja/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/ja/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/ka/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/ka/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/kn/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/kn/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/ko/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/ko/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/lt/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/lt/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/lv/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/lv/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/ml/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/ml/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/nb/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/nb/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/nl/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/nl/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/nn/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/nn/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/pl/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/pl/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/pt_BR/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/pt_BR/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/pt_PT/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/pt_PT/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/ro/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/ro/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/ru/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/ru/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/si/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/si/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/sk/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/sk/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/sl/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/sl/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/sr/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/sr/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/sv/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/sv/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/th/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/th/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/tr/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/tr/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/uk/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/uk/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/vi/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/vi/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/zh_CN/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/zh_CN/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
1817
src/iOS.Safari/Resources/_locales/zh_TW/messages.json
Normal file
1817
src/iOS.Safari/Resources/_locales/zh_TW/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
7
src/iOS.Safari/Resources/background.html
Normal file
7
src/iOS.Safari/Resources/background.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<script src="vendor.js"></script><script src="background.js"></script></body>
|
||||
</html>
|
||||
30039
src/iOS.Safari/Resources/background.js
Normal file
30039
src/iOS.Safari/Resources/background.js
Normal file
File diff suppressed because one or more lines are too long
36
src/iOS.Safari/Resources/content/autofill.css
Normal file
36
src/iOS.Safari/Resources/content/autofill.css
Normal file
@@ -0,0 +1,36 @@
|
||||
@-webkit-keyframes bitwardenfill {
|
||||
0% {
|
||||
-webkit-transform: scale(1.0, 1.0);
|
||||
}
|
||||
|
||||
50% {
|
||||
-webkit-transform: scale(1.2, 1.2);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: scale(1.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes bitwardenfill {
|
||||
0% {
|
||||
transform: scale(1.0, 1.0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(1.2, 1.2);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
span[data-bwautofill].com-bitwarden-browser-animated-fill {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.com-bitwarden-browser-animated-fill {
|
||||
animation: bitwardenfill 200ms ease-in-out 0ms 1;
|
||||
-webkit-animation: bitwardenfill 200ms ease-in-out 0ms 1;
|
||||
}
|
||||
1142
src/iOS.Safari/Resources/content/autofill.js
Normal file
1142
src/iOS.Safari/Resources/content/autofill.js
Normal file
File diff suppressed because it is too large
Load Diff
139
src/iOS.Safari/Resources/content/autofiller.js
Normal file
139
src/iOS.Safari/Resources/content/autofiller.js
Normal file
@@ -0,0 +1,139 @@
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // define __esModule on exports
|
||||
/******/ __webpack_require__.r = function(exports) {
|
||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||
/******/ }
|
||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // create a fake namespace object
|
||||
/******/ // mode & 1: value is a module id, require it
|
||||
/******/ // mode & 2: merge all properties of value into the ns
|
||||
/******/ // mode & 4: return value when already ns object
|
||||
/******/ // mode & 8|1: behave like require
|
||||
/******/ __webpack_require__.t = function(value, mode) {
|
||||
/******/ if(mode & 1) value = __webpack_require__(value);
|
||||
/******/ if(mode & 8) return value;
|
||||
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
||||
/******/ var ns = Object.create(null);
|
||||
/******/ __webpack_require__.r(ns);
|
||||
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
||||
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
||||
/******/ return ns;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = "./src/content/autofiller.ts");
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
||||
/***/ "./src/content/autofiller.ts":
|
||||
/*!***********************************!*\
|
||||
!*** ./src/content/autofiller.ts ***!
|
||||
\***********************************/
|
||||
/*! no static exports found */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
document.addEventListener('DOMContentLoaded', event => {
|
||||
let pageHref = null;
|
||||
let filledThisHref = false;
|
||||
let delayFillTimeout;
|
||||
const enabledKey = 'enableAutoFillOnPageLoad';
|
||||
chrome.storage.local.get(enabledKey, (obj) => {
|
||||
if (obj != null && obj[enabledKey] === true) {
|
||||
setInterval(() => doFillIfNeeded(), 500);
|
||||
}
|
||||
});
|
||||
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||
if (msg.command === 'fillForm' && pageHref === msg.url) {
|
||||
filledThisHref = true;
|
||||
}
|
||||
});
|
||||
function doFillIfNeeded(force = false) {
|
||||
if (force || pageHref !== window.location.href) {
|
||||
if (!force) {
|
||||
// Some websites are slow and rendering all page content. Try to fill again later
|
||||
// if we haven't already.
|
||||
filledThisHref = false;
|
||||
if (delayFillTimeout != null) {
|
||||
window.clearTimeout(delayFillTimeout);
|
||||
}
|
||||
delayFillTimeout = window.setTimeout(() => {
|
||||
if (!filledThisHref) {
|
||||
doFillIfNeeded(true);
|
||||
}
|
||||
}, 1500);
|
||||
}
|
||||
pageHref = window.location.href;
|
||||
const msg = {
|
||||
command: 'bgCollectPageDetails',
|
||||
sender: 'autofiller',
|
||||
};
|
||||
chrome.runtime.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
159
src/iOS.Safari/Resources/content/contextMenuHandler.js
Normal file
159
src/iOS.Safari/Resources/content/contextMenuHandler.js
Normal file
@@ -0,0 +1,159 @@
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // define __esModule on exports
|
||||
/******/ __webpack_require__.r = function(exports) {
|
||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||
/******/ }
|
||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // create a fake namespace object
|
||||
/******/ // mode & 1: value is a module id, require it
|
||||
/******/ // mode & 2: merge all properties of value into the ns
|
||||
/******/ // mode & 4: return value when already ns object
|
||||
/******/ // mode & 8|1: behave like require
|
||||
/******/ __webpack_require__.t = function(value, mode) {
|
||||
/******/ if(mode & 1) value = __webpack_require__(value);
|
||||
/******/ if(mode & 8) return value;
|
||||
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
||||
/******/ var ns = Object.create(null);
|
||||
/******/ __webpack_require__.r(ns);
|
||||
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
||||
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
||||
/******/ return ns;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = "./src/content/contextMenuHandler.ts");
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
||||
/***/ "./src/content/contextMenuHandler.ts":
|
||||
/*!*******************************************!*\
|
||||
!*** ./src/content/contextMenuHandler.ts ***!
|
||||
\*******************************************/
|
||||
/*! no static exports found */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
const inputTags = ['input', 'textarea', 'select'];
|
||||
const labelTags = ['label', 'span'];
|
||||
const attributes = ['id', 'name', 'label-aria', 'placeholder'];
|
||||
const invalidElement = chrome.i18n.getMessage('copyCustomFieldNameInvalidElement');
|
||||
const noUniqueIdentifier = chrome.i18n.getMessage('copyCustomFieldNameNotUnique');
|
||||
let clickedEl = null;
|
||||
// Find the best attribute to be used as the Name for an element in a custom field.
|
||||
function getClickedElementIdentifier() {
|
||||
var _a, _b;
|
||||
if (clickedEl == null) {
|
||||
return invalidElement;
|
||||
}
|
||||
const clickedTag = clickedEl.nodeName.toLowerCase();
|
||||
let inputEl = null;
|
||||
// Try to identify the input element (which may not be the clicked element)
|
||||
if (labelTags.includes(clickedTag)) {
|
||||
let inputId = null;
|
||||
if (clickedTag === 'label') {
|
||||
inputId = clickedEl.getAttribute('for');
|
||||
}
|
||||
else {
|
||||
inputId = (_a = clickedEl.closest('label')) === null || _a === void 0 ? void 0 : _a.getAttribute('for');
|
||||
}
|
||||
inputEl = document.getElementById(inputId);
|
||||
}
|
||||
else {
|
||||
inputEl = clickedEl;
|
||||
}
|
||||
if (inputEl == null || !inputTags.includes(inputEl.nodeName.toLowerCase())) {
|
||||
return invalidElement;
|
||||
}
|
||||
for (const attr of attributes) {
|
||||
const attributeValue = inputEl.getAttribute(attr);
|
||||
const selector = '[' + attr + '="' + attributeValue + '"]';
|
||||
if (!isNullOrEmpty(attributeValue) && ((_b = document.querySelectorAll(selector)) === null || _b === void 0 ? void 0 : _b.length) === 1) {
|
||||
return attributeValue;
|
||||
}
|
||||
}
|
||||
return noUniqueIdentifier;
|
||||
}
|
||||
function isNullOrEmpty(s) {
|
||||
return s == null || s === '';
|
||||
}
|
||||
// We only have access to the element that's been clicked when the context menu is first opened.
|
||||
// Remember it for use later.
|
||||
document.addEventListener('contextmenu', event => {
|
||||
clickedEl = event.target;
|
||||
});
|
||||
// Runs when the 'Copy Custom Field Name' context menu item is actually clicked.
|
||||
chrome.runtime.onMessage.addListener(event => {
|
||||
if (event.command === 'getClickedElement') {
|
||||
const identifier = getClickedElementIdentifier();
|
||||
chrome.runtime.sendMessage({
|
||||
command: 'getClickedElementResponse',
|
||||
sender: 'contextMenuHandler',
|
||||
identifier: identifier,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
126
src/iOS.Safari/Resources/content/message_handler.js
Normal file
126
src/iOS.Safari/Resources/content/message_handler.js
Normal file
@@ -0,0 +1,126 @@
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // define __esModule on exports
|
||||
/******/ __webpack_require__.r = function(exports) {
|
||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||
/******/ }
|
||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // create a fake namespace object
|
||||
/******/ // mode & 1: value is a module id, require it
|
||||
/******/ // mode & 2: merge all properties of value into the ns
|
||||
/******/ // mode & 4: return value when already ns object
|
||||
/******/ // mode & 8|1: behave like require
|
||||
/******/ __webpack_require__.t = function(value, mode) {
|
||||
/******/ if(mode & 1) value = __webpack_require__(value);
|
||||
/******/ if(mode & 8) return value;
|
||||
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
||||
/******/ var ns = Object.create(null);
|
||||
/******/ __webpack_require__.r(ns);
|
||||
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
||||
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
||||
/******/ return ns;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = "./src/content/message_handler.ts");
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
||||
/***/ "./src/content/message_handler.ts":
|
||||
/*!****************************************!*\
|
||||
!*** ./src/content/message_handler.ts ***!
|
||||
\****************************************/
|
||||
/*! no static exports found */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
window.addEventListener('message', event => {
|
||||
if (event.source !== window)
|
||||
return;
|
||||
if (event.data.command && (event.data.command === 'authResult')) {
|
||||
chrome.runtime.sendMessage({
|
||||
command: event.data.command,
|
||||
code: event.data.code,
|
||||
state: event.data.state,
|
||||
referrer: event.source.location.hostname,
|
||||
});
|
||||
}
|
||||
if (event.data.command && (event.data.command === 'webAuthnResult')) {
|
||||
chrome.runtime.sendMessage({
|
||||
command: event.data.command,
|
||||
data: event.data.data,
|
||||
remember: event.data.remember,
|
||||
referrer: event.source.location.hostname,
|
||||
});
|
||||
}
|
||||
}, false);
|
||||
const forwardCommands = ['promptForLogin', 'addToLockedVaultPendingNotifications', 'unlockCompleted'];
|
||||
chrome.runtime.onMessage.addListener(event => {
|
||||
if (forwardCommands.includes(event.command)) {
|
||||
chrome.runtime.sendMessage(event);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
592
src/iOS.Safari/Resources/content/notificationBar.js
Normal file
592
src/iOS.Safari/Resources/content/notificationBar.js
Normal file
@@ -0,0 +1,592 @@
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // define __esModule on exports
|
||||
/******/ __webpack_require__.r = function(exports) {
|
||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||
/******/ }
|
||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // create a fake namespace object
|
||||
/******/ // mode & 1: value is a module id, require it
|
||||
/******/ // mode & 2: merge all properties of value into the ns
|
||||
/******/ // mode & 4: return value when already ns object
|
||||
/******/ // mode & 8|1: behave like require
|
||||
/******/ __webpack_require__.t = function(value, mode) {
|
||||
/******/ if(mode & 1) value = __webpack_require__(value);
|
||||
/******/ if(mode & 8) return value;
|
||||
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
||||
/******/ var ns = Object.create(null);
|
||||
/******/ __webpack_require__.r(ns);
|
||||
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
||||
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
||||
/******/ return ns;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = "./src/content/notificationBar.ts");
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
||||
/***/ "./src/content/notificationBar.ts":
|
||||
/*!****************************************!*\
|
||||
!*** ./src/content/notificationBar.ts ***!
|
||||
\****************************************/
|
||||
/*! no exports provided */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
__webpack_require__.r(__webpack_exports__);
|
||||
document.addEventListener('DOMContentLoaded', event => {
|
||||
if (window.location.hostname.indexOf('vault.bitwarden.com') > -1) {
|
||||
return;
|
||||
}
|
||||
const pageDetails = [];
|
||||
const formData = [];
|
||||
let barType = null;
|
||||
let pageHref = null;
|
||||
let observer = null;
|
||||
const observeIgnoredElements = new Set(['a', 'i', 'b', 'strong', 'span', 'code', 'br', 'img', 'small', 'em', 'hr']);
|
||||
let domObservationCollectTimeout = null;
|
||||
let collectIfNeededTimeout = null;
|
||||
let observeDomTimeout = null;
|
||||
const inIframe = isInIframe();
|
||||
const cancelButtonNames = new Set(['cancel', 'close', 'back']);
|
||||
const logInButtonNames = new Set(['log in', 'sign in', 'login', 'go', 'submit', 'continue', 'next']);
|
||||
const changePasswordButtonNames = new Set(['save password', 'update password', 'change password', 'change']);
|
||||
const changePasswordButtonContainsNames = new Set(['pass', 'change', 'contras', 'senha']);
|
||||
let disabledAddLoginNotification = false;
|
||||
let disabledChangedPasswordNotification = false;
|
||||
chrome.storage.local.get('neverDomains', (ndObj) => {
|
||||
const domains = ndObj.neverDomains;
|
||||
if (domains != null && domains.hasOwnProperty(window.location.hostname)) {
|
||||
return;
|
||||
}
|
||||
chrome.storage.local.get('disableAddLoginNotification', (disAddObj) => {
|
||||
disabledAddLoginNotification = disAddObj != null && disAddObj.disableAddLoginNotification === true;
|
||||
chrome.storage.local.get('disableChangedPasswordNotification', (disChangedObj) => {
|
||||
disabledChangedPasswordNotification = disChangedObj != null &&
|
||||
disChangedObj.disableChangedPasswordNotification === true;
|
||||
if (!disabledAddLoginNotification || !disabledChangedPasswordNotification) {
|
||||
collectIfNeededWithTimeout();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||
processMessages(msg, sendResponse);
|
||||
});
|
||||
function processMessages(msg, sendResponse) {
|
||||
if (msg.command === 'openNotificationBar') {
|
||||
if (inIframe) {
|
||||
return;
|
||||
}
|
||||
closeExistingAndOpenBar(msg.data.type, msg.data.typeData);
|
||||
sendResponse();
|
||||
return true;
|
||||
}
|
||||
else if (msg.command === 'closeNotificationBar') {
|
||||
if (inIframe) {
|
||||
return;
|
||||
}
|
||||
closeBar(true);
|
||||
sendResponse();
|
||||
return true;
|
||||
}
|
||||
else if (msg.command === 'adjustNotificationBar') {
|
||||
if (inIframe) {
|
||||
return;
|
||||
}
|
||||
adjustBar(msg.data);
|
||||
sendResponse();
|
||||
return true;
|
||||
}
|
||||
else if (msg.command === 'notificationBarPageDetails') {
|
||||
pageDetails.push(msg.data.details);
|
||||
watchForms(msg.data.forms);
|
||||
sendResponse();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
function isInIframe() {
|
||||
try {
|
||||
return window.self !== window.top;
|
||||
}
|
||||
catch (_a) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
function observeDom() {
|
||||
const bodies = document.querySelectorAll('body');
|
||||
if (bodies && bodies.length > 0) {
|
||||
observer = new MutationObserver(mutations => {
|
||||
if (mutations == null || mutations.length === 0 || pageHref !== window.location.href) {
|
||||
return;
|
||||
}
|
||||
let doCollect = false;
|
||||
for (let i = 0; i < mutations.length; i++) {
|
||||
const mutation = mutations[i];
|
||||
if (mutation.addedNodes == null || mutation.addedNodes.length === 0) {
|
||||
continue;
|
||||
}
|
||||
for (let j = 0; j < mutation.addedNodes.length; j++) {
|
||||
const addedNode = mutation.addedNodes[j];
|
||||
if (addedNode == null) {
|
||||
continue;
|
||||
}
|
||||
const tagName = addedNode.tagName != null ? addedNode.tagName.toLowerCase() : null;
|
||||
if (tagName != null && tagName === 'form' &&
|
||||
(addedNode.dataset == null || !addedNode.dataset.bitwardenWatching)) {
|
||||
doCollect = true;
|
||||
break;
|
||||
}
|
||||
if ((tagName != null && observeIgnoredElements.has(tagName)) ||
|
||||
addedNode.querySelectorAll == null) {
|
||||
continue;
|
||||
}
|
||||
const forms = addedNode.querySelectorAll('form:not([data-bitwarden-watching])');
|
||||
if (forms != null && forms.length > 0) {
|
||||
doCollect = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (doCollect) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (doCollect) {
|
||||
if (domObservationCollectTimeout != null) {
|
||||
window.clearTimeout(domObservationCollectTimeout);
|
||||
}
|
||||
domObservationCollectTimeout = window.setTimeout(collect, 1000);
|
||||
}
|
||||
});
|
||||
observer.observe(bodies[0], { childList: true, subtree: true });
|
||||
}
|
||||
}
|
||||
function collectIfNeededWithTimeout() {
|
||||
if (collectIfNeededTimeout != null) {
|
||||
window.clearTimeout(collectIfNeededTimeout);
|
||||
}
|
||||
collectIfNeededTimeout = window.setTimeout(collectIfNeeded, 1000);
|
||||
}
|
||||
function collectIfNeeded() {
|
||||
if (pageHref !== window.location.href) {
|
||||
pageHref = window.location.href;
|
||||
if (observer) {
|
||||
observer.disconnect();
|
||||
observer = null;
|
||||
}
|
||||
collect();
|
||||
if (observeDomTimeout != null) {
|
||||
window.clearTimeout(observeDomTimeout);
|
||||
}
|
||||
observeDomTimeout = window.setTimeout(observeDom, 1000);
|
||||
}
|
||||
if (collectIfNeededTimeout != null) {
|
||||
window.clearTimeout(collectIfNeededTimeout);
|
||||
}
|
||||
collectIfNeededTimeout = window.setTimeout(collectIfNeeded, 1000);
|
||||
}
|
||||
function collect() {
|
||||
sendPlatformMessage({
|
||||
command: 'bgCollectPageDetails',
|
||||
sender: 'notificationBar',
|
||||
});
|
||||
}
|
||||
function watchForms(forms) {
|
||||
if (forms == null || forms.length === 0) {
|
||||
return;
|
||||
}
|
||||
forms.forEach((f) => {
|
||||
const formId = f.form != null ? f.form.htmlID : null;
|
||||
let formEl = null;
|
||||
if (formId != null && formId !== '') {
|
||||
formEl = document.getElementById(formId);
|
||||
}
|
||||
if (formEl == null) {
|
||||
const index = parseInt(f.form.opid.split('__')[2], null);
|
||||
formEl = document.getElementsByTagName('form')[index];
|
||||
}
|
||||
if (formEl != null && formEl.dataset.bitwardenWatching !== '1') {
|
||||
const formDataObj = {
|
||||
data: f,
|
||||
formEl: formEl,
|
||||
usernameEl: null,
|
||||
passwordEl: null,
|
||||
passwordEls: null,
|
||||
};
|
||||
locateFields(formDataObj);
|
||||
formData.push(formDataObj);
|
||||
listen(formEl);
|
||||
formEl.dataset.bitwardenWatching = '1';
|
||||
}
|
||||
});
|
||||
}
|
||||
function listen(form) {
|
||||
form.removeEventListener('submit', formSubmitted, false);
|
||||
form.addEventListener('submit', formSubmitted, false);
|
||||
const submitButton = getSubmitButton(form, logInButtonNames);
|
||||
if (submitButton != null) {
|
||||
submitButton.removeEventListener('click', formSubmitted, false);
|
||||
submitButton.addEventListener('click', formSubmitted, false);
|
||||
}
|
||||
}
|
||||
function locateFields(formDataObj) {
|
||||
const inputs = Array.from(document.getElementsByTagName('input'));
|
||||
formDataObj.usernameEl = locateField(formDataObj.formEl, formDataObj.data.username, inputs);
|
||||
if (formDataObj.usernameEl != null && formDataObj.data.password != null) {
|
||||
formDataObj.passwordEl = locatePassword(formDataObj.formEl, formDataObj.data.password, inputs, true);
|
||||
}
|
||||
else if (formDataObj.data.passwords != null) {
|
||||
formDataObj.passwordEls = [];
|
||||
formDataObj.data.passwords.forEach((pData) => {
|
||||
const el = locatePassword(formDataObj.formEl, pData, inputs, false);
|
||||
if (el != null) {
|
||||
formDataObj.passwordEls.push(el);
|
||||
}
|
||||
});
|
||||
if (formDataObj.passwordEls.length === 0) {
|
||||
formDataObj.passwordEls = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
function locatePassword(form, passwordData, inputs, doLastFallback) {
|
||||
let el = locateField(form, passwordData, inputs);
|
||||
if (el != null && el.type !== 'password') {
|
||||
el = null;
|
||||
}
|
||||
if (doLastFallback && el == null) {
|
||||
el = form.querySelector('input[type="password"]');
|
||||
}
|
||||
return el;
|
||||
}
|
||||
function locateField(form, fieldData, inputs) {
|
||||
if (fieldData == null) {
|
||||
return;
|
||||
}
|
||||
let el = null;
|
||||
if (fieldData.htmlID != null && fieldData.htmlID !== '') {
|
||||
try {
|
||||
el = form.querySelector('#' + fieldData.htmlID);
|
||||
}
|
||||
catch (_a) {
|
||||
// Ignore error, we perform fallbacks below.
|
||||
}
|
||||
}
|
||||
if (el == null && fieldData.htmlName != null && fieldData.htmlName !== '') {
|
||||
el = form.querySelector('input[name="' + fieldData.htmlName + '"]');
|
||||
}
|
||||
if (el == null && fieldData.elementNumber != null) {
|
||||
el = inputs[fieldData.elementNumber];
|
||||
}
|
||||
return el;
|
||||
}
|
||||
function formSubmitted(e) {
|
||||
let form = null;
|
||||
if (e.type === 'click') {
|
||||
form = e.target.closest('form');
|
||||
if (form == null) {
|
||||
const parentModal = e.target.closest('div.modal');
|
||||
if (parentModal != null) {
|
||||
const modalForms = parentModal.querySelectorAll('form');
|
||||
if (modalForms.length === 1) {
|
||||
form = modalForms[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
form = e.target;
|
||||
}
|
||||
if (form == null || form.dataset.bitwardenProcessed === '1') {
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < formData.length; i++) {
|
||||
if (formData[i].formEl !== form) {
|
||||
continue;
|
||||
}
|
||||
const disabledBoth = disabledChangedPasswordNotification && disabledAddLoginNotification;
|
||||
if (!disabledBoth && formData[i].usernameEl != null && formData[i].passwordEl != null) {
|
||||
const login = {
|
||||
username: formData[i].usernameEl.value,
|
||||
password: formData[i].passwordEl.value,
|
||||
url: document.URL,
|
||||
};
|
||||
if (login.username != null && login.username !== '' &&
|
||||
login.password != null && login.password !== '') {
|
||||
processedForm(form);
|
||||
sendPlatformMessage({
|
||||
command: 'bgAddLogin',
|
||||
login: login,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!disabledChangedPasswordNotification && formData[i].passwordEls != null) {
|
||||
const passwords = formData[i].passwordEls
|
||||
.filter((el) => el.value != null && el.value !== '')
|
||||
.map((el) => el.value);
|
||||
let curPass = null;
|
||||
let newPass = null;
|
||||
let newPassOnly = false;
|
||||
if (formData[i].passwordEls.length === 3 && passwords.length === 3) {
|
||||
newPass = passwords[1];
|
||||
if (passwords[0] !== newPass && newPass === passwords[2]) {
|
||||
curPass = passwords[0];
|
||||
}
|
||||
else if (newPass !== passwords[2] && passwords[0] === newPass) {
|
||||
curPass = passwords[2];
|
||||
}
|
||||
}
|
||||
else if (formData[i].passwordEls.length === 2 && passwords.length === 2) {
|
||||
if (passwords[0] === passwords[1]) {
|
||||
newPassOnly = true;
|
||||
newPass = passwords[0];
|
||||
curPass = null;
|
||||
}
|
||||
else {
|
||||
const buttonText = getButtonText(getSubmitButton(form, changePasswordButtonNames));
|
||||
const matches = Array.from(changePasswordButtonContainsNames)
|
||||
.filter(n => buttonText.indexOf(n) > -1);
|
||||
if (matches.length > 0) {
|
||||
curPass = passwords[0];
|
||||
newPass = passwords[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newPass != null && curPass != null || (newPassOnly && newPass != null)) {
|
||||
processedForm(form);
|
||||
const changePasswordRuntimeMessage = {
|
||||
newPassword: newPass,
|
||||
currentPassword: curPass,
|
||||
url: document.URL,
|
||||
};
|
||||
sendPlatformMessage({
|
||||
command: 'bgChangedPassword',
|
||||
data: changePasswordRuntimeMessage,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function getSubmitButton(wrappingEl, buttonNames) {
|
||||
if (wrappingEl == null) {
|
||||
return null;
|
||||
}
|
||||
const wrappingElIsForm = wrappingEl.tagName.toLowerCase() === 'form';
|
||||
let submitButton = wrappingEl.querySelector('input[type="submit"], input[type="image"], ' +
|
||||
'button[type="submit"]');
|
||||
if (submitButton == null && wrappingElIsForm) {
|
||||
submitButton = wrappingEl.querySelector('button:not([type])');
|
||||
if (submitButton != null) {
|
||||
const buttonText = getButtonText(submitButton);
|
||||
if (buttonText != null && cancelButtonNames.has(buttonText.trim().toLowerCase())) {
|
||||
submitButton = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (submitButton == null) {
|
||||
const possibleSubmitButtons = Array.from(wrappingEl.querySelectorAll('a, span, button[type="button"], ' +
|
||||
'input[type="button"], button:not([type])'));
|
||||
let typelessButton = null;
|
||||
possibleSubmitButtons.forEach(button => {
|
||||
if (submitButton != null || button == null || button.tagName == null) {
|
||||
return;
|
||||
}
|
||||
const buttonText = getButtonText(button);
|
||||
if (buttonText != null) {
|
||||
if (typelessButton != null && button.tagName.toLowerCase() === 'button' &&
|
||||
button.getAttribute('type') == null &&
|
||||
!cancelButtonNames.has(buttonText.trim().toLowerCase())) {
|
||||
typelessButton = button;
|
||||
}
|
||||
else if (buttonNames.has(buttonText.trim().toLowerCase())) {
|
||||
submitButton = button;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (submitButton == null && typelessButton != null) {
|
||||
submitButton = typelessButton;
|
||||
}
|
||||
}
|
||||
if (submitButton == null && wrappingElIsForm) {
|
||||
// Maybe it's in a modal?
|
||||
const parentModal = wrappingEl.closest('div.modal');
|
||||
if (parentModal != null) {
|
||||
const modalForms = parentModal.querySelectorAll('form');
|
||||
if (modalForms.length === 1) {
|
||||
submitButton = getSubmitButton(parentModal, buttonNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
return submitButton;
|
||||
}
|
||||
function getButtonText(button) {
|
||||
let buttonText = null;
|
||||
if (button.tagName.toLowerCase() === 'input') {
|
||||
buttonText = button.value;
|
||||
}
|
||||
else {
|
||||
buttonText = button.innerText;
|
||||
}
|
||||
return buttonText;
|
||||
}
|
||||
function processedForm(form) {
|
||||
form.dataset.bitwardenProcessed = '1';
|
||||
window.setTimeout(() => {
|
||||
form.dataset.bitwardenProcessed = '0';
|
||||
}, 500);
|
||||
}
|
||||
function closeExistingAndOpenBar(type, typeData) {
|
||||
let barPage = 'notification/bar.html';
|
||||
switch (type) {
|
||||
case 'add':
|
||||
barPage = barPage + '?add=1&isVaultLocked=' + typeData.isVaultLocked;
|
||||
break;
|
||||
case 'change':
|
||||
barPage = barPage + '?change=1&isVaultLocked=' + typeData.isVaultLocked;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const frame = document.getElementById('bit-notification-bar-iframe');
|
||||
if (frame != null && frame.src.indexOf(barPage) >= 0) {
|
||||
return;
|
||||
}
|
||||
closeBar(false);
|
||||
openBar(type, barPage);
|
||||
}
|
||||
function openBar(type, barPage) {
|
||||
barType = type;
|
||||
if (document.body == null) {
|
||||
return;
|
||||
}
|
||||
const barPageUrl = chrome.extension.getURL(barPage);
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.style.cssText = 'height: 42px; width: 100%; border: 0; min-height: initial;';
|
||||
iframe.id = 'bit-notification-bar-iframe';
|
||||
iframe.src = barPageUrl;
|
||||
const frameDiv = document.createElement('div');
|
||||
frameDiv.setAttribute('aria-live', 'polite');
|
||||
frameDiv.id = 'bit-notification-bar';
|
||||
frameDiv.style.cssText = 'height: 42px; width: 100%; top: 0; left: 0; padding: 0; position: fixed; ' +
|
||||
'z-index: 2147483647; visibility: visible;';
|
||||
frameDiv.appendChild(iframe);
|
||||
document.body.appendChild(frameDiv);
|
||||
iframe.contentWindow.location = barPageUrl;
|
||||
const spacer = document.createElement('div');
|
||||
spacer.id = 'bit-notification-bar-spacer';
|
||||
spacer.style.cssText = 'height: 42px;';
|
||||
document.body.insertBefore(spacer, document.body.firstChild);
|
||||
}
|
||||
function closeBar(explicitClose) {
|
||||
const barEl = document.getElementById('bit-notification-bar');
|
||||
if (barEl != null) {
|
||||
barEl.parentElement.removeChild(barEl);
|
||||
}
|
||||
const spacerEl = document.getElementById('bit-notification-bar-spacer');
|
||||
if (spacerEl) {
|
||||
spacerEl.parentElement.removeChild(spacerEl);
|
||||
}
|
||||
if (!explicitClose) {
|
||||
return;
|
||||
}
|
||||
switch (barType) {
|
||||
case 'add':
|
||||
sendPlatformMessage({
|
||||
command: 'bgAddClose',
|
||||
});
|
||||
break;
|
||||
case 'change':
|
||||
sendPlatformMessage({
|
||||
command: 'bgChangeClose',
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
function adjustBar(data) {
|
||||
if (data != null && data.height !== 42) {
|
||||
const newHeight = data.height + 'px';
|
||||
doHeightAdjustment('bit-notification-bar-iframe', newHeight);
|
||||
doHeightAdjustment('bit-notification-bar', newHeight);
|
||||
doHeightAdjustment('bit-notification-bar-spacer', newHeight);
|
||||
}
|
||||
}
|
||||
function doHeightAdjustment(elId, heightStyle) {
|
||||
const el = document.getElementById(elId);
|
||||
if (el != null) {
|
||||
el.style.height = heightStyle;
|
||||
}
|
||||
}
|
||||
function sendPlatformMessage(msg) {
|
||||
chrome.runtime.sendMessage(msg);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user