mirror of
https://github.com/bitwarden/mobile
synced 2025-12-05 23:53:33 +00:00
Compare commits
84 Commits
CLOUDOPS-2
...
community/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95f5a1ce09 | ||
|
|
c4790eb78e | ||
|
|
8577765668 | ||
|
|
f63918aa4e | ||
|
|
f42c677d5a | ||
|
|
5a56d64211 | ||
|
|
0bd1b3f45f | ||
|
|
3780587991 | ||
|
|
6875389948 | ||
|
|
0e5d6e79c5 | ||
|
|
490b74dd26 | ||
|
|
66d05e1b00 | ||
|
|
3d3101c3ab | ||
|
|
ccde4270d0 | ||
|
|
a1f799302e | ||
|
|
4619e257e8 | ||
|
|
c54a14cd3f | ||
|
|
a96d95c95b | ||
|
|
e61ca489ce | ||
|
|
c3ad5f0580 | ||
|
|
8b08f906bd | ||
|
|
4ad5f5ae37 | ||
|
|
68a6449339 | ||
|
|
b8d53b0f81 | ||
|
|
dbfd15b819 | ||
|
|
acd0cb119d | ||
|
|
d61bc4b5c1 | ||
|
|
5aa1146657 | ||
|
|
f15fd246a8 | ||
|
|
2b8547878a | ||
|
|
942d5d29d2 | ||
|
|
fde63a836d | ||
|
|
6102a0c115 | ||
|
|
4f4953206e | ||
|
|
f772ee7068 | ||
|
|
8f93e6bf5f | ||
|
|
64fefac194 | ||
|
|
d784b1290b | ||
|
|
0f2bc2fa25 | ||
|
|
0e856d2add | ||
|
|
acc587ce45 | ||
|
|
66180397d9 | ||
|
|
571c4b8d22 | ||
|
|
660ba3d722 | ||
|
|
414cb9bd7e | ||
|
|
e588efd0a1 | ||
|
|
1cdba5f73d | ||
|
|
cbccd10271 | ||
|
|
6de6b19944 | ||
|
|
5493b00957 | ||
|
|
81988a7fe7 | ||
|
|
b91ff09e27 | ||
|
|
945627d649 | ||
|
|
307c71ee07 | ||
|
|
e72932cbaa | ||
|
|
4347c2f81d | ||
|
|
619acfe0fe | ||
|
|
05765c2af9 | ||
|
|
728182de6c | ||
|
|
a19b5c4e05 | ||
|
|
f6895a0733 | ||
|
|
3e48b7a968 | ||
|
|
ebf65ecb96 | ||
|
|
37dab0928b | ||
|
|
aa0544cd3d | ||
|
|
f4b4cfc9de | ||
|
|
7785b2dbf9 | ||
|
|
e3dafb502b | ||
|
|
b30fc12135 | ||
|
|
28d204f2b1 | ||
|
|
1a3ff5ec41 | ||
|
|
2f6fd476a2 | ||
|
|
7a08452fa8 | ||
|
|
fa6bac3b43 | ||
|
|
2a60ff62d8 | ||
|
|
eaa4f193ce | ||
|
|
6973a0b71c | ||
|
|
bafd9ff85d | ||
|
|
4580033477 | ||
|
|
a4673021a9 | ||
|
|
8e2e143e6f | ||
|
|
f43f9171e5 | ||
|
|
3c8a8862ca | ||
|
|
969b89bb4d |
@@ -14,6 +14,10 @@
|
|||||||
<string>Dist: Extension 2021</string>
|
<string>Dist: Extension 2021</string>
|
||||||
<key>com.8bit.bitwarden.share-extension</key>
|
<key>com.8bit.bitwarden.share-extension</key>
|
||||||
<string>Dist: Share Extension 2021</string>
|
<string>Dist: Share Extension 2021</string>
|
||||||
|
<key>com.8bit.bitwarden.watchkitapp</key>
|
||||||
|
<string>Dist: Bitwarden Watch App</string>
|
||||||
|
<key>com.8bit.bitwarden.watchkitapp.watchkitextension</key>
|
||||||
|
<string>Dist: Bitwarden Watch App Extension</string>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
BIN
.github/secrets/GoogleService-Info.plist.gpg
vendored
Normal file
BIN
.github/secrets/GoogleService-Info.plist.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/dist_watch_app.mobileprovision.gpg
vendored
Normal file
BIN
.github/secrets/dist_watch_app.mobileprovision.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/dist_watch_app_extension.mobileprovision.gpg
vendored
Normal file
BIN
.github/secrets/dist_watch_app_extension.mobileprovision.gpg
vendored
Normal file
Binary file not shown.
204
.github/workflows/build.yml
vendored
204
.github/workflows/build.yml
vendored
@@ -4,16 +4,13 @@ name: Build
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches-ignore:
|
branches-ignore:
|
||||||
- 'l10n_master'
|
- "l10n_master"
|
||||||
- 'gh-pages'
|
- "gh-pages"
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '.github/workflows/**'
|
- ".github/workflows/**"
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs: {}
|
inputs: {}
|
||||||
|
|
||||||
env:
|
|
||||||
BASE_PKG_NAME: com.x8bit.bitwarden
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
cloc:
|
cloc:
|
||||||
name: CLOC
|
name: CLOC
|
||||||
@@ -45,15 +42,15 @@ jobs:
|
|||||||
id: branch-check
|
id: branch-check
|
||||||
run: |
|
run: |
|
||||||
if [[ $(git ls-remote --heads origin rc) ]]; then
|
if [[ $(git ls-remote --heads origin rc) ]]; then
|
||||||
echo "::set-output name=rc_branch_exists::1"
|
echo "rc_branch_exists=1" >> $GITHUB_OUTPUT
|
||||||
else
|
else
|
||||||
echo "::set-output name=rc_branch_exists::0"
|
echo "rc_branch_exists=0" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $(git ls-remote --heads origin hotfix-rc) ]]; then
|
if [[ $(git ls-remote --heads origin hotfix-rc) ]]; then
|
||||||
echo "::set-output name=hotfix_branch_exists::1"
|
echo "hotfix_branch_exists=1" >> $GITHUB_OUTPUT
|
||||||
else
|
else
|
||||||
echo "::set-output name=hotfix_branch_exists::0"
|
echo "hotfix_branch_exists=0" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
@@ -65,16 +62,19 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
variant: ['prod', 'qa']
|
variant: ["prod", "qa"]
|
||||||
steps:
|
steps:
|
||||||
- name: Setup NuGet
|
- name: Setup NuGet
|
||||||
uses: nuget/setup-nuget@b2bc17b761a1d88cab755a776c7922eb26eefbfa # v1.0.6
|
uses: nuget/setup-nuget@b2bc17b761a1d88cab755a776c7922eb26eefbfa # v1.0.6
|
||||||
with:
|
with:
|
||||||
nuget-version: 5.9.0
|
nuget-version: 5.9.0
|
||||||
|
|
||||||
- name: Set up MSBuild
|
- name: Set up MSBuild
|
||||||
uses: microsoft/setup-msbuild@ab534842b4bdf384b8aaf93765dc6f721d9f5fab
|
uses: microsoft/setup-msbuild@ab534842b4bdf384b8aaf93765dc6f721d9f5fab
|
||||||
|
|
||||||
|
- name: Setup Windows builder
|
||||||
|
run: choco install checksum --no-progress
|
||||||
|
|
||||||
- name: Work Around for broken Windows 2022 Runner Image
|
- name: Work Around for broken Windows 2022 Runner Image
|
||||||
run: |
|
run: |
|
||||||
Set-Location "C:\Program Files (x86)\Microsoft Visual Studio\Installer\"
|
Set-Location "C:\Program Files (x86)\Microsoft Visual Studio\Installer\"
|
||||||
@@ -151,7 +151,17 @@ jobs:
|
|||||||
shell: pwsh
|
shell: pwsh
|
||||||
|
|
||||||
- name: Run Core tests
|
- name: Run Core tests
|
||||||
run: dotnet test test/Core.Test/Core.Test.csproj
|
run: dotnet test test/Core.Test/Core.Test.csproj --logger "trx;LogFileName=test-results.trx"
|
||||||
|
shell: pwsh
|
||||||
|
|
||||||
|
- name: Report test results
|
||||||
|
uses: dorny/test-reporter@c9b3d0e2bd2a4e96aaf424dbaa31c46b42318226
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: Test Results
|
||||||
|
path: "**/test-results.trx"
|
||||||
|
reporter: dotnet-trx
|
||||||
|
fail-on-error: true
|
||||||
|
|
||||||
- name: Build Play Store publisher
|
- name: Build Play Store publisher
|
||||||
if: ${{ matrix.variant == 'prod' }}
|
if: ${{ matrix.variant == 'prod' }}
|
||||||
@@ -177,11 +187,11 @@ jobs:
|
|||||||
UPLOAD_KEYSTORE_PASSWORD: ${{ secrets.UPLOAD_KEYSTORE_PASSWORD }}
|
UPLOAD_KEYSTORE_PASSWORD: ${{ secrets.UPLOAD_KEYSTORE_PASSWORD }}
|
||||||
run: |
|
run: |
|
||||||
$androidPath = $($env:GITHUB_WORKSPACE + "/src/Android/Android.csproj");
|
$androidPath = $($env:GITHUB_WORKSPACE + "/src/Android/Android.csproj");
|
||||||
$packageName = "";
|
$packageName = "com.x8bit.bitwarden";
|
||||||
|
|
||||||
if ("${{ matrix.variant }}" -ne "prod")
|
if ("${{ matrix.variant }}" -ne "prod")
|
||||||
{
|
{
|
||||||
$packageName = "${{ env.BASE_PKG_NAME }}.${{ matrix.variant }}";
|
$packageName = "com.x8bit.bitwarden.${{ matrix.variant }}";
|
||||||
}
|
}
|
||||||
Write-Output "########################################"
|
Write-Output "########################################"
|
||||||
Write-Output "##### Sign Google Play Bundle Release Configuration"
|
Write-Output "##### Sign Google Play Bundle Release Configuration"
|
||||||
@@ -222,24 +232,52 @@ jobs:
|
|||||||
if: ${{ matrix.variant == 'prod' }}
|
if: ${{ matrix.variant == 'prod' }}
|
||||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||||
with:
|
with:
|
||||||
name: ${{ env.BASE_PKG_NAME }}.aab
|
name: com.x8bit.bitwarden.aab
|
||||||
path: ./${{ env.BASE_PKG_NAME }}.aab
|
path: ./com.x8bit.bitwarden.aab
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload Prod .apk artifact
|
- name: Upload Prod .apk artifact
|
||||||
if: ${{ matrix.variant == 'prod' }}
|
if: ${{ matrix.variant == 'prod' }}
|
||||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||||
with:
|
with:
|
||||||
name: ${{ env.BASE_PKG_NAME }}.apk
|
name: com.x8bit.bitwarden.apk
|
||||||
path: ./${{ env.BASE_PKG_NAME }}.apk
|
path: ./com.x8bit.bitwarden.apk
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload Other .apk artifact
|
- name: Upload Other .apk artifact
|
||||||
if: ${{ matrix.variant != 'prod' }}
|
if: ${{ matrix.variant != 'prod' }}
|
||||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||||
with:
|
with:
|
||||||
name: ${{ env.BASE_PKG_NAME }}.${{ matrix.variant }}.apk
|
name: com.x8bit.bitwarden.${{ matrix.variant }}.apk
|
||||||
path: ./${{ env.BASE_PKG_NAME }}.${{ matrix.variant }}.apk
|
path: ./com.x8bit.bitwarden.${{ matrix.variant }}.apk
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Create checksum for Prod .apk artifact
|
||||||
|
if: ${{ matrix.variant == 'prod' }}
|
||||||
|
run: |
|
||||||
|
checksum -f="./com.x8bit.bitwarden.apk" `
|
||||||
|
-t sha256 | Out-File -Encoding ASCII ./bw-android-apk-sha256.txt
|
||||||
|
|
||||||
|
- name: Create checksum for Other .apk artifact
|
||||||
|
if: ${{ matrix.variant != 'prod' }}
|
||||||
|
run: |
|
||||||
|
checksum -f="./com.x8bit.bitwarden.${{ matrix.variant }}.apk" `
|
||||||
|
-t sha256 | Out-File -Encoding ASCII ./bw-android-${{ matrix.variant }}-apk-sha256.txt
|
||||||
|
|
||||||
|
- name: Upload .apk sha file for prod
|
||||||
|
if: ${{ matrix.variant == 'prod' }}
|
||||||
|
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||||
|
with:
|
||||||
|
name: bw-android-apk-sha256.txt
|
||||||
|
path: ./bw-android-apk-sha256.txt
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Upload .apk sha file for other
|
||||||
|
if: ${{ matrix.variant != 'prod' }}
|
||||||
|
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||||
|
with:
|
||||||
|
name: bw-android-${{ matrix.variant }}-apk-sha256.txt
|
||||||
|
path: ./bw-android-${{ matrix.variant }}-apk-sha256.txt
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Deploy to Play Store
|
- name: Deploy to Play Store
|
||||||
@@ -251,10 +289,10 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
PUBLISHER_PATH="$GITHUB_WORKSPACE/store/google/Publisher/bin/Release/netcoreapp3.1/Publisher.dll"
|
PUBLISHER_PATH="$GITHUB_WORKSPACE/store/google/Publisher/bin/Release/netcoreapp3.1/Publisher.dll"
|
||||||
CREDS_PATH="$HOME/secrets/play_creds.json"
|
CREDS_PATH="$HOME/secrets/play_creds.json"
|
||||||
AAB_PATH="$GITHUB_WORKSPACE/${{env:BASE_PKG_NAME}}.aab"
|
AAB_PATH="$GITHUB_WORKSPACE/com.x8bit.bitwarden.aab"
|
||||||
TRACK="internal"
|
TRACK="internal"
|
||||||
|
|
||||||
dotnet $PUBLISHER_PATH $CREDS_PATH $AAB_PATH $TRACK ${{env:BASE_PKG_NAME}}
|
dotnet $PUBLISHER_PATH $CREDS_PATH $AAB_PATH $TRACK
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
|
|
||||||
@@ -263,13 +301,16 @@ jobs:
|
|||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
steps:
|
steps:
|
||||||
- name: Setup NuGet
|
- name: Setup NuGet
|
||||||
uses: nuget/setup-nuget@b2bc17b761a1d88cab755a776c7922eb26eefbfa # v1.0.6
|
uses: nuget/setup-nuget@b2bc17b761a1d88cab755a776c7922eb26eefbfa # v1.0.6
|
||||||
with:
|
with:
|
||||||
nuget-version: 5.9.0
|
nuget-version: 5.9.0
|
||||||
|
|
||||||
- name: Set up MSBuild
|
- name: Set up MSBuild
|
||||||
uses: microsoft/setup-msbuild@ab534842b4bdf384b8aaf93765dc6f721d9f5fab
|
uses: microsoft/setup-msbuild@ab534842b4bdf384b8aaf93765dc6f721d9f5fab
|
||||||
|
|
||||||
|
- name: Setup Windows builder
|
||||||
|
run: choco install checksum --no-progress
|
||||||
|
|
||||||
- name: Work Around for broken Windows 2022 Runner Image
|
- name: Work Around for broken Windows 2022 Runner Image
|
||||||
run: |
|
run: |
|
||||||
Set-Location "C:\Program Files (x86)\Microsoft Visual Studio\Installer\"
|
Set-Location "C:\Program Files (x86)\Microsoft Visual Studio\Installer\"
|
||||||
@@ -427,8 +468,8 @@ jobs:
|
|||||||
Write-Output "##### Copy FDroid apk to project root"
|
Write-Output "##### Copy FDroid apk to project root"
|
||||||
Write-Output "########################################"
|
Write-Output "########################################"
|
||||||
|
|
||||||
$signedApkPath = $($env:GITHUB_WORKSPACE + "/src/Android/bin/FDroid/$env:BASE_PKG_NAME-Signed.apk");
|
$signedApkPath = $($env:GITHUB_WORKSPACE + "/src/Android/bin/FDroid/com.x8bit.bitwarden-Signed.apk");
|
||||||
$signedApkDestPath = $($env:GITHUB_WORKSPACE + "/$env:BASE_PKG_NAME-fdroid.apk");
|
$signedApkDestPath = $($env:GITHUB_WORKSPACE + "/com.x8bit.bitwarden-fdroid.apk");
|
||||||
|
|
||||||
Copy-Item $signedApkPath $signedApkDestPath
|
Copy-Item $signedApkPath $signedApkDestPath
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
@@ -436,18 +477,30 @@ jobs:
|
|||||||
- name: Upload F-Droid .apk artifact
|
- name: Upload F-Droid .apk artifact
|
||||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||||
with:
|
with:
|
||||||
name: ${{ env.BASE_PKG_NAME }}.apk
|
name: com.x8bit.bitwarden-fdroid.apk
|
||||||
path: ./${{ env.BASE_PKG_NAME }}.apk
|
path: ./com.x8bit.bitwarden-fdroid.apk
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Create checksum for F-Droid artifact
|
||||||
|
run: |
|
||||||
|
checksum -f="./com.x8bit.bitwarden-fdroid.apk" `
|
||||||
|
-t sha256 | Out-File -Encoding ASCII ./bw-fdroid-apk-sha256.txt
|
||||||
|
|
||||||
|
- name: Upload F-Droid sha file
|
||||||
|
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
|
||||||
|
with:
|
||||||
|
name: bw-fdroid-apk-sha256.txt
|
||||||
|
path: ./bw-fdroid-apk-sha256.txt
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
|
|
||||||
ios:
|
ios:
|
||||||
name: Apple iOS
|
name: Apple iOS
|
||||||
runs-on: macos-11
|
runs-on: macos-12
|
||||||
needs: setup
|
needs: setup
|
||||||
steps:
|
steps:
|
||||||
- name: Setup NuGet
|
- name: Setup NuGet
|
||||||
uses: nuget/setup-nuget@b2bc17b761a1d88cab755a776c7922eb26eefbfa # v1.0.6
|
uses: nuget/setup-nuget@b2bc17b761a1d88cab755a776c7922eb26eefbfa # v1.0.6
|
||||||
with:
|
with:
|
||||||
nuget-version: 5.9.0
|
nuget-version: 5.9.0
|
||||||
|
|
||||||
@@ -478,7 +531,7 @@ jobs:
|
|||||||
do
|
do
|
||||||
VALUE=$(az keyvault secret show --vault-name $KEYVAULT --name $i --query value --output tsv)
|
VALUE=$(az keyvault secret show --vault-name $KEYVAULT --name $i --query value --output tsv)
|
||||||
echo "::add-mask::$VALUE"
|
echo "::add-mask::$VALUE"
|
||||||
echo "::set-output name=$i::$VALUE"
|
echo "$i=$VALUE" >> $GITHUB_OUTPUT
|
||||||
done
|
done
|
||||||
|
|
||||||
- name: Decrypt secrets
|
- name: Decrypt secrets
|
||||||
@@ -500,6 +553,14 @@ jobs:
|
|||||||
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||||
--output $HOME/secrets/dist_share_extension.mobileprovision \
|
--output $HOME/secrets/dist_share_extension.mobileprovision \
|
||||||
./.github/secrets/dist_share_extension.mobileprovision.gpg
|
./.github/secrets/dist_share_extension.mobileprovision.gpg
|
||||||
|
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||||
|
--output $HOME/secrets/dist_watch_app.mobileprovision \
|
||||||
|
./.github/secrets/dist_watch_app.mobileprovision.gpg
|
||||||
|
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||||
|
--output $HOME/secrets/dist_watch_app_extension.mobileprovision \
|
||||||
|
./.github/secrets/dist_watch_app_extension.mobileprovision.gpg
|
||||||
|
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
|
||||||
|
--output ./src/watchOS/bitwarden/GoogleService-Info.plist ./.github/secrets/GoogleService-Info.plist.gpg
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Increment version
|
- name: Increment version
|
||||||
@@ -514,6 +575,9 @@ jobs:
|
|||||||
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Extension/Info.plist
|
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Extension/Info.plist
|
||||||
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Autofill/Info.plist
|
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Autofill/Info.plist
|
||||||
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.ShareExtension/Info.plist
|
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.ShareExtension/Info.plist
|
||||||
|
cd src/watchOS/bitwarden
|
||||||
|
agvtool new-version -all $BUILD_NUMBER
|
||||||
|
cd ../../..
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Update Entitlements
|
- name: Update Entitlements
|
||||||
@@ -548,6 +612,8 @@ jobs:
|
|||||||
BITWARDEN_PROFILE_PATH=$HOME/secrets/dist_bitwarden.mobileprovision
|
BITWARDEN_PROFILE_PATH=$HOME/secrets/dist_bitwarden.mobileprovision
|
||||||
EXTENSION_PROFILE_PATH=$HOME/secrets/dist_extension.mobileprovision
|
EXTENSION_PROFILE_PATH=$HOME/secrets/dist_extension.mobileprovision
|
||||||
SHARE_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_share_extension.mobileprovision
|
SHARE_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_share_extension.mobileprovision
|
||||||
|
WATCH_APP_PROFILE_PATH=$HOME/secrets/dist_watch_app.mobileprovision
|
||||||
|
WATCH_APP_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_watch_app_extension.mobileprovision
|
||||||
PROFILES_DIR_PATH=$HOME/Library/MobileDevice/Provisioning\ Profiles
|
PROFILES_DIR_PATH=$HOME/Library/MobileDevice/Provisioning\ Profiles
|
||||||
|
|
||||||
mkdir -p "$PROFILES_DIR_PATH"
|
mkdir -p "$PROFILES_DIR_PATH"
|
||||||
@@ -563,6 +629,25 @@ jobs:
|
|||||||
|
|
||||||
SHARE_EXTENSION_UUID=$(grep UUID -A1 -a $SHARE_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
|
SHARE_EXTENSION_UUID=$(grep UUID -A1 -a $SHARE_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
|
||||||
cp $SHARE_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$SHARE_EXTENSION_UUID.mobileprovision"
|
cp $SHARE_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$SHARE_EXTENSION_UUID.mobileprovision"
|
||||||
|
|
||||||
|
WATCH_APP_UUID=$(grep UUID -A1 -a $WATCH_APP_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
|
||||||
|
cp $WATCH_APP_PROFILE_PATH "$PROFILES_DIR_PATH/$WATCH_APP_UUID.mobileprovision"
|
||||||
|
|
||||||
|
WATCH_APP_EXTENSION_UUID=$(grep UUID -A1 -a $WATCH_APP_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
|
||||||
|
cp $WATCH_APP_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$WATCH_APP_EXTENSION_UUID.mobileprovision"
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
- name: Bulid WatchApp
|
||||||
|
run: |
|
||||||
|
echo "########################################"
|
||||||
|
echo "##### Build WatchApp with Release Configuration"
|
||||||
|
echo "########################################"
|
||||||
|
|
||||||
|
xcodebuild archive -workspace ./src/watchOS/bitwarden/bitwarden.xcodeproj/project.xcworkspace -configuration Release -scheme bitwarden\ WatchKit\ App -archivePath ./src/watchOS/bitwarden
|
||||||
|
|
||||||
|
echo "########################################"
|
||||||
|
echo "##### Done"
|
||||||
|
echo "########################################"
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Restore packages
|
- name: Restore packages
|
||||||
@@ -600,7 +685,12 @@ jobs:
|
|||||||
ARCHIVE_DSYMS_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive/dSYMs"
|
ARCHIVE_DSYMS_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive/dSYMs"
|
||||||
EXPORT_PATH="./bitwarden-export"
|
EXPORT_PATH="./bitwarden-export"
|
||||||
|
|
||||||
cp -r $ARCHIVE_DSYMS_PATH $EXPORT_PATH
|
WATCH_ARCHIVE_DSYMS_PATH="./src/watchOS/bitwarden.xcarchive/dSYMs/"
|
||||||
|
WATCH_DSYMS_EXPORT_PATH="$EXPORT_PATH/Watch_dSYMs"
|
||||||
|
|
||||||
|
cp -r -v $ARCHIVE_DSYMS_PATH $EXPORT_PATH
|
||||||
|
mkdir $WATCH_DSYMS_EXPORT_PATH
|
||||||
|
cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Upload App Store .ipa & dSYMs artifacts
|
- name: Upload App Store .ipa & dSYMs artifacts
|
||||||
@@ -623,23 +713,39 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload dSYMs to App Center
|
- name: Upload dSYMs to App Center
|
||||||
if: |
|
if: |
|
||||||
(github.ref == 'refs/heads/master'
|
(github.ref == 'refs/heads/master'
|
||||||
&& needs.setup.outputs.rc_branch_exists == 0
|
&& needs.setup.outputs.rc_branch_exists == 0
|
||||||
&& needs.setup.outputs.hotfix_branch_exists == 0)
|
&& needs.setup.outputs.hotfix_branch_exists == 0)
|
||||||
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|
||||||
|| github.ref == 'refs/heads/hotfix-rc'
|
|| github.ref == 'refs/heads/hotfix-rc'
|
||||||
env:
|
env:
|
||||||
APPCENTER_IOS_TOKEN: ${{ steps.retrieve-secrets.outputs.appcenter-ios-token }}
|
APPCENTER_IOS_TOKEN: ${{ steps.retrieve-secrets.outputs.appcenter-ios-token }}
|
||||||
run: appcenter crashes upload-symbols -a bitwarden/bitwarden -s "./bitwarden-export/dSYMs" --token $APPCENTER_IOS_TOKEN
|
run: appcenter crashes upload-symbols -a bitwarden/bitwarden -s "./bitwarden-export/dSYMs" --token $APPCENTER_IOS_TOKEN
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
|
- name: Upload Watch dSYMs to Firebase Crashlytics
|
||||||
|
if: |
|
||||||
|
(github.ref == 'refs/heads/master'
|
||||||
|
&& needs.setup.outputs.rc_branch_exists == 0
|
||||||
|
&& needs.setup.outputs.hotfix_branch_exists == 0)
|
||||||
|
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|
||||||
|
|| github.ref == 'refs/heads/hotfix-rc'
|
||||||
|
run: |
|
||||||
|
|
||||||
|
echo "########################################"
|
||||||
|
echo "##### Uploading Watch dSYMs to Firebase"
|
||||||
|
echo "########################################"
|
||||||
|
|
||||||
|
find "$HOME/Library/Developer/XCode/DerivedData" -name "upload-symbols" -exec chmod +x {} \; -exec {} -gsp "./src/watchOS/bitwarden/GoogleService-Info.plist" -p ios "./bitwarden-export/Watch_dSYMs" \;
|
||||||
|
shell: bash
|
||||||
|
|
||||||
- name: Deploy to App Store
|
- name: Deploy to App Store
|
||||||
if: |
|
if: |
|
||||||
(github.ref == 'refs/heads/master'
|
(github.ref == 'refs/heads/master'
|
||||||
&& needs.setup.outputs.rc_branch_exists == 0
|
&& needs.setup.outputs.rc_branch_exists == 0
|
||||||
&& needs.setup.outputs.hotfix_branch_exists == 0)
|
&& needs.setup.outputs.hotfix_branch_exists == 0)
|
||||||
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|
||||||
|| github.ref == 'refs/heads/hotfix-rc'
|
|| github.ref == 'refs/heads/hotfix-rc'
|
||||||
env:
|
env:
|
||||||
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
|
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
|
||||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||||
@@ -679,7 +785,7 @@ jobs:
|
|||||||
do
|
do
|
||||||
VALUE=$(az keyvault secret show --vault-name $KEYVAULT --name $i --query value --output tsv)
|
VALUE=$(az keyvault secret show --vault-name $KEYVAULT --name $i --query value --output tsv)
|
||||||
echo "::add-mask::$VALUE"
|
echo "::add-mask::$VALUE"
|
||||||
echo "::set-output name=$i::$VALUE"
|
echo "$i=$VALUE" >> $GITHUB_OUTPUT
|
||||||
done
|
done
|
||||||
|
|
||||||
- name: Upload Sources
|
- name: Upload Sources
|
||||||
@@ -707,9 +813,9 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Check if any job failed
|
- name: Check if any job failed
|
||||||
if: |
|
if: |
|
||||||
(github.ref == 'refs/heads/master')
|
(github.ref == 'refs/heads/master')
|
||||||
|| (github.ref == 'refs/heads/rc')
|
|| (github.ref == 'refs/heads/rc')
|
||||||
|| (github.ref == 'refs/heads/hotfix-rc')
|
|| (github.ref == 'refs/heads/hotfix-rc')
|
||||||
env:
|
env:
|
||||||
CLOC_STATUS: ${{ needs.cloc.result }}
|
CLOC_STATUS: ${{ needs.cloc.result }}
|
||||||
ANDROID_STATUS: ${{ needs.android.result }}
|
ANDROID_STATUS: ${{ needs.android.result }}
|
||||||
@@ -747,7 +853,7 @@ jobs:
|
|||||||
do
|
do
|
||||||
VALUE=$(az keyvault secret show --vault-name $KEYVAULT --name $i --query value --output tsv)
|
VALUE=$(az keyvault secret show --vault-name $KEYVAULT --name $i --query value --output tsv)
|
||||||
echo "::add-mask::$VALUE"
|
echo "::add-mask::$VALUE"
|
||||||
echo "::set-output name=$i::$VALUE"
|
echo "$i=$VALUE" >> $GITHUB_OUTPUT
|
||||||
done
|
done
|
||||||
|
|
||||||
- name: Notify Slack on failure
|
- name: Notify Slack on failure
|
||||||
|
|||||||
4
.github/workflows/enforce-labels.yml
vendored
4
.github/workflows/enforce-labels.yml
vendored
@@ -12,5 +12,5 @@ jobs:
|
|||||||
- name: Enforce Label
|
- name: Enforce Label
|
||||||
uses: yogevbd/enforce-label-action@8d1e1709b1011e6d90400a0e6cf7c0b77aa5efeb
|
uses: yogevbd/enforce-label-action@8d1e1709b1011e6d90400a0e6cf7c0b77aa5efeb
|
||||||
with:
|
with:
|
||||||
BANNED_LABELS: "hold"
|
BANNED_LABELS: "hold,needs-qa"
|
||||||
BANNED_LABELS_DESCRIPTION: "PRs on hold cannot be merged"
|
BANNED_LABELS_DESCRIPTION: "PRs with the hold or needs-qa labels cannot be merged"
|
||||||
|
|||||||
23
.github/workflows/release.yml
vendored
23
.github/workflows/release.yml
vendored
@@ -20,9 +20,6 @@ on:
|
|||||||
default: true
|
default: true
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|
||||||
env:
|
|
||||||
BASE_PKG_NAME: com.x8bit.bitwarden
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
name: Create Release
|
name: Create Release
|
||||||
@@ -55,7 +52,7 @@ jobs:
|
|||||||
id: branch
|
id: branch
|
||||||
run: |
|
run: |
|
||||||
BRANCH_NAME=$(basename ${{ github.ref }})
|
BRANCH_NAME=$(basename ${{ github.ref }})
|
||||||
echo "::set-output name=branch-name::$BRANCH_NAME"
|
echo "branch-name=$BRANCH_NAME" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Create GitHub deployment
|
- name: Create GitHub deployment
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
@@ -67,7 +64,7 @@ jobs:
|
|||||||
environment: 'production'
|
environment: 'production'
|
||||||
description: 'Deployment ${{ steps.version.outputs.version }} from branch ${{ steps.branch.outputs.branch-name }}'
|
description: 'Deployment ${{ steps.version.outputs.version }} from branch ${{ steps.branch.outputs.branch-name }}'
|
||||||
task: release
|
task: release
|
||||||
|
|
||||||
|
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
@@ -92,10 +89,12 @@ jobs:
|
|||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
||||||
uses: ncipollo/release-action@40bb172bd05f266cf9ba4ff965cb61e9ee5f6d01 # v1.9.0
|
uses: ncipollo/release-action@40bb172bd05f266cf9ba4ff965cb61e9ee5f6d01 # v1.9.0
|
||||||
with:
|
with:
|
||||||
artifacts: "./${{ BASE_PKG_NAME }}.aab/${{ BASE_PKG_NAME }}.aab,
|
artifacts: "./com.x8bit.bitwarden.aab/com.x8bit.bitwarden.aab,
|
||||||
./${{ BASE_PKG_NAME }}.apk/${{ BASE_PKG_NAME }}.apk,
|
./com.x8bit.bitwarden.apk/com.x8bit.bitwarden.apk,
|
||||||
./${{ BASE_PKG_NAME }}-fdroid.apk/${{ BASE_PKG_NAME }}-fdroid.apk,
|
./com.x8bit.bitwarden-fdroid.apk/com.x8bit.bitwarden-fdroid.apk,
|
||||||
./Bitwarden iOS.zip"
|
./Bitwarden iOS.zip,
|
||||||
|
./bw-android-apk-sha256.txt,
|
||||||
|
./bw-fdroid-apk-sha256.txt"
|
||||||
commit: ${{ github.sha }}
|
commit: ${{ github.sha }}
|
||||||
tag: v${{ steps.version.outputs.version }}
|
tag: v${{ steps.version.outputs.version }}
|
||||||
name: Version ${{ steps.version.outputs.version }}
|
name: Version ${{ steps.version.outputs.version }}
|
||||||
@@ -136,7 +135,7 @@ jobs:
|
|||||||
workflow: build.yml
|
workflow: build.yml
|
||||||
workflow_conclusion: success
|
workflow_conclusion: success
|
||||||
branch: ${{ needs.release.outputs.branch-name }}
|
branch: ${{ needs.release.outputs.branch-name }}
|
||||||
name: ${{ BASE_PKG_NAME }}-fdroid.apk
|
name: com.x8bit.bitwarden-fdroid.apk
|
||||||
|
|
||||||
- name: Dry Run - Download F-Droid .apk artifact
|
- name: Dry Run - Download F-Droid .apk artifact
|
||||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
||||||
@@ -145,7 +144,7 @@ jobs:
|
|||||||
workflow: build.yml
|
workflow: build.yml
|
||||||
workflow_conclusion: success
|
workflow_conclusion: success
|
||||||
branch: master
|
branch: master
|
||||||
name: ${{ BASE_PKG_NAME }}-fdroid.apk
|
name: com.x8bit.bitwarden-fdroid.apk
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561 # v2.5.1
|
uses: actions/setup-node@1f8c6b94b26d0feae1e387ca63ccbdc44d27b561 # v2.5.1
|
||||||
@@ -201,7 +200,7 @@ jobs:
|
|||||||
echo "keystorepass=\"$FDROID_STORE_KEYSTORE_PASSWORD\"" >>config.py
|
echo "keystorepass=\"$FDROID_STORE_KEYSTORE_PASSWORD\"" >>config.py
|
||||||
echo "local_copy_dir=\"$TEMP_DIR\"" >>config.py
|
echo "local_copy_dir=\"$TEMP_DIR\"" >>config.py
|
||||||
mkdir -p repo
|
mkdir -p repo
|
||||||
mv $GITHUB_WORKSPACE/${{ BASE_PKG_NAME }}-fdroid.apk ./repo/
|
mv $GITHUB_WORKSPACE/com.x8bit.bitwarden-fdroid.apk ./repo/
|
||||||
fdroid update
|
fdroid update
|
||||||
fdroid server update
|
fdroid server update
|
||||||
cd ..
|
cd ..
|
||||||
|
|||||||
6
.github/workflows/version-auto-bump.yml
vendored
6
.github/workflows/version-auto-bump.yml
vendored
@@ -21,15 +21,15 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
RELEASE_TAG: ${{ github.ref }}
|
RELEASE_TAG: ${{ github.ref }}
|
||||||
run: |
|
run: |
|
||||||
CURR_MAJOR=$(echo $RELEASE_TAG | sed -r 's/v([0-9]{4}\.[0-9]{1,2})\.([0-9]{1,2})/\1/')
|
CURR_MAJOR=$(echo $RELEASE_TAG | sed -r 's/refs\/tags\/v([0-9]{4}\.[0-9]{1,2})\.([0-9]{1,2})/\1/')
|
||||||
CURR_PATCH=$(echo $RELEASE_TAG | sed -r 's/v([0-9]{4}\.[0-9]{1,2})\.([0-9]{1,2})/\2/')
|
CURR_PATCH=$(echo $RELEASE_TAG | sed -r 's/refs\/tags\/v([0-9]{4}\.[0-9]{1,2})\.([0-9]{1,2})/\2/')
|
||||||
echo "Current Major: $CURR_MAJOR"
|
echo "Current Major: $CURR_MAJOR"
|
||||||
echo "Current Patch: $CURR_PATCH"
|
echo "Current Patch: $CURR_PATCH"
|
||||||
|
|
||||||
NEW_PATCH=$((CURR_PATCH+1))
|
NEW_PATCH=$((CURR_PATCH+1))
|
||||||
NEW_VER=$CURR_MAJOR.$NEW_PATCH
|
NEW_VER=$CURR_MAJOR.$NEW_PATCH
|
||||||
echo "New Version: $NEW_VER"
|
echo "New Version: $NEW_VER"
|
||||||
echo "::set-output name=new-version::$NEW_VER"
|
echo "new-version=$NEW_VER" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
trigger_version_bump:
|
trigger_version_bump:
|
||||||
name: "Trigger version bump workflow"
|
name: "Trigger version bump workflow"
|
||||||
|
|||||||
10
.github/workflows/version-bump.yml
vendored
10
.github/workflows/version-bump.yml
vendored
@@ -37,8 +37,7 @@ jobs:
|
|||||||
git_commit_gpgsign: true
|
git_commit_gpgsign: true
|
||||||
|
|
||||||
- name: Create Version Branch
|
- name: Create Version Branch
|
||||||
run: |
|
run: git switch -c version_bump_${{ github.event.inputs.version_number }}
|
||||||
git switch -c version_bump_${{ github.event.inputs.version_number }}
|
|
||||||
|
|
||||||
- name: Bump Version - Android XML
|
- name: Bump Version - Android XML
|
||||||
uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
|
uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
|
||||||
@@ -79,16 +78,15 @@ jobs:
|
|||||||
id: version-changed
|
id: version-changed
|
||||||
run: |
|
run: |
|
||||||
if [ -n "$(git status --porcelain)" ]; then
|
if [ -n "$(git status --porcelain)" ]; then
|
||||||
echo "::set-output name=changes_to_commit::TRUE"
|
echo "changes_to_commit=TRUE" >> $GITHUB_OUTPUT
|
||||||
else
|
else
|
||||||
echo "::set-output name=changes_to_commit::FALSE"
|
echo "changes_to_commit=FALSE" >> $GITHUB_OUTPUT
|
||||||
echo "No changes to commit!";
|
echo "No changes to commit!";
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Commit files
|
- name: Commit files
|
||||||
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
||||||
run: |
|
run: git commit -m "Bumped version to ${{ github.event.inputs.version_number }}" -a
|
||||||
git commit -m "Bumped version to ${{ github.event.inputs.version_number }}" -a
|
|
||||||
|
|
||||||
- name: Push changes
|
- name: Push changes
|
||||||
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
||||||
|
|||||||
126
.gitignore
vendored
126
.gitignore
vendored
@@ -30,6 +30,7 @@ Components/
|
|||||||
[Rr]eleases/
|
[Rr]eleases/
|
||||||
x64/
|
x64/
|
||||||
x86/
|
x86/
|
||||||
|
!src/lib/x86/
|
||||||
build/
|
build/
|
||||||
bld/
|
bld/
|
||||||
[Bb]in/
|
[Bb]in/
|
||||||
@@ -210,3 +211,128 @@ project.lock.json
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
src/App/Css
|
src/App/Css
|
||||||
tools
|
tools
|
||||||
|
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/swift,objective-c
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=swift,objective-c
|
||||||
|
|
||||||
|
### Objective-C ###
|
||||||
|
# Xcode
|
||||||
|
#
|
||||||
|
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||||
|
|
||||||
|
## User settings
|
||||||
|
xcuserdata/
|
||||||
|
|
||||||
|
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
|
||||||
|
*.xcscmblueprint
|
||||||
|
*.xccheckout
|
||||||
|
|
||||||
|
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
|
||||||
|
build/
|
||||||
|
DerivedData/
|
||||||
|
*.moved-aside
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
|
||||||
|
## Obj-C/Swift specific
|
||||||
|
*.hmap
|
||||||
|
|
||||||
|
## App packaging
|
||||||
|
*.ipa
|
||||||
|
*.dSYM.zip
|
||||||
|
*.dSYM
|
||||||
|
|
||||||
|
# CocoaPods
|
||||||
|
# We recommend against adding the Pods directory to your .gitignore. However
|
||||||
|
# you should judge for yourself, the pros and cons are mentioned at:
|
||||||
|
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||||
|
# Pods/
|
||||||
|
# Add this line if you want to avoid checking in source code from the Xcode workspace
|
||||||
|
# *.xcworkspace
|
||||||
|
|
||||||
|
# Carthage
|
||||||
|
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||||
|
# Carthage/Checkouts
|
||||||
|
|
||||||
|
Carthage/Build/
|
||||||
|
|
||||||
|
# fastlane
|
||||||
|
# It is recommended to not store the screenshots in the git repo.
|
||||||
|
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
|
||||||
|
# For more information about the recommended setup visit:
|
||||||
|
# https://docs.fastlane.tools/best-practices/source-control/#source-control
|
||||||
|
|
||||||
|
fastlane/report.xml
|
||||||
|
fastlane/Preview.html
|
||||||
|
fastlane/screenshots/**/*.png
|
||||||
|
fastlane/test_output
|
||||||
|
|
||||||
|
# Code Injection
|
||||||
|
# After new code Injection tools there's a generated folder /iOSInjectionProject
|
||||||
|
# https://github.com/johnno1962/injectionforxcode
|
||||||
|
|
||||||
|
iOSInjectionProject/
|
||||||
|
|
||||||
|
### Objective-C Patch ###
|
||||||
|
|
||||||
|
### Swift ###
|
||||||
|
# Xcode
|
||||||
|
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Playgrounds
|
||||||
|
timeline.xctimeline
|
||||||
|
playground.xcworkspace
|
||||||
|
|
||||||
|
# Swift Package Manager
|
||||||
|
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
|
||||||
|
# Packages/
|
||||||
|
# Package.pins
|
||||||
|
# Package.resolved
|
||||||
|
# *.xcodeproj
|
||||||
|
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
|
||||||
|
# hence it is not needed unless you have added a package configuration file to your project
|
||||||
|
# .swiftpm
|
||||||
|
|
||||||
|
.build/
|
||||||
|
|
||||||
|
# CocoaPods
|
||||||
|
# We recommend against adding the Pods directory to your .gitignore. However
|
||||||
|
# you should judge for yourself, the pros and cons are mentioned at:
|
||||||
|
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||||
|
# Pods/
|
||||||
|
# Add this line if you want to avoid checking in source code from the Xcode workspace
|
||||||
|
# *.xcworkspace
|
||||||
|
|
||||||
|
# Carthage
|
||||||
|
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||||
|
# Carthage/Checkouts
|
||||||
|
|
||||||
|
|
||||||
|
# Accio dependency management
|
||||||
|
Dependencies/
|
||||||
|
.accio/
|
||||||
|
|
||||||
|
# fastlane
|
||||||
|
# It is recommended to not store the screenshots in the git repo.
|
||||||
|
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
|
||||||
|
# For more information about the recommended setup visit:
|
||||||
|
# https://docs.fastlane.tools/best-practices/source-control/#source-control
|
||||||
|
|
||||||
|
|
||||||
|
# Code Injection
|
||||||
|
# After new code Injection tools there's a generated folder /iOSInjectionProject
|
||||||
|
# https://github.com/johnno1962/injectionforxcode
|
||||||
|
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/swift,objective-c
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ The Bitwarden mobile application is written in C# with Xamarin Android, Xamarin
|
|||||||
|
|
||||||
# Build/Run
|
# Build/Run
|
||||||
|
|
||||||
Please refer to the [Mobile section](https://contributing.bitwarden.com/mobile/) of the [Contributing Documentation](https://contributing.bitwarden.com/) for build instructions, recommended tooling, code style tips, and lots of other great information to get you started.
|
Please refer to the [Mobile section](https://contributing.bitwarden.com/getting-started/clients/mobile/) of the [Contributing Documentation](https://contributing.bitwarden.com/) for build instructions, recommended tooling, code style tips, and lots of other great information to get you started.
|
||||||
|
|
||||||
# We're Hiring!
|
# We're Hiring!
|
||||||
|
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ Task("UpdateAndroidCodeFiles")
|
|||||||
Path.Combine(_slnPath, "src", "Android", "Receivers", "PackageReplacedReceiver.cs"),
|
Path.Combine(_slnPath, "src", "Android", "Receivers", "PackageReplacedReceiver.cs"),
|
||||||
Path.Combine(_slnPath, "src", "Android", "Receivers", "RestrictionsChangedReceiver.cs"),
|
Path.Combine(_slnPath, "src", "Android", "Receivers", "RestrictionsChangedReceiver.cs"),
|
||||||
Path.Combine(_slnPath, "src", "Android", "Services", "DeviceActionService.cs"),
|
Path.Combine(_slnPath, "src", "Android", "Services", "DeviceActionService.cs"),
|
||||||
|
Path.Combine(_slnPath, "src", "Android", "Services", "FileService.cs"),
|
||||||
Path.Combine(_slnPath, "src", "Android", "Tiles", "AutofillTileService.cs"),
|
Path.Combine(_slnPath, "src", "Android", "Tiles", "AutofillTileService.cs"),
|
||||||
Path.Combine(_slnPath, "src", "Android", "Tiles", "GeneratorTileService.cs"),
|
Path.Combine(_slnPath, "src", "Android", "Tiles", "GeneratorTileService.cs"),
|
||||||
Path.Combine(_slnPath, "src", "Android", "Tiles", "MyVaultTileService.cs"),
|
Path.Combine(_slnPath, "src", "Android", "Tiles", "MyVaultTileService.cs"),
|
||||||
|
|||||||
BIN
lib/ios/libargon2.a
Normal file
BIN
lib/ios/libargon2.a
Normal file
Binary file not shown.
@@ -33,6 +33,7 @@ namespace Bit.Droid.Accessibility
|
|||||||
// - Resources/xml/autofillservice.xml
|
// - Resources/xml/autofillservice.xml
|
||||||
new Browser("alook.browser", "search_fragment_input_view"),
|
new Browser("alook.browser", "search_fragment_input_view"),
|
||||||
new Browser("alook.browser.google", "search_fragment_input_view"),
|
new Browser("alook.browser.google", "search_fragment_input_view"),
|
||||||
|
new Browser("app.vanadium.browser", "url_bar"),
|
||||||
new Browser("com.amazon.cloud9", "url"),
|
new Browser("com.amazon.cloud9", "url"),
|
||||||
new Browser("com.android.browser", "url"),
|
new Browser("com.android.browser", "url"),
|
||||||
new Browser("com.android.chrome", "url_bar"),
|
new Browser("com.android.chrome", "url_bar"),
|
||||||
@@ -66,6 +67,7 @@ namespace Bit.Droid.Accessibility
|
|||||||
new Browser("com.mmbox.xbrowser", "search_box"),
|
new Browser("com.mmbox.xbrowser", "search_box"),
|
||||||
new Browser("com.mycompany.app.soulbrowser", "edit_text"),
|
new Browser("com.mycompany.app.soulbrowser", "edit_text"),
|
||||||
new Browser("com.naver.whale", "url_bar"),
|
new Browser("com.naver.whale", "url_bar"),
|
||||||
|
new Browser("com.neeva.app", "full_url_text_view"),
|
||||||
new Browser("com.opera.browser", "url_field"),
|
new Browser("com.opera.browser", "url_field"),
|
||||||
new Browser("com.opera.browser.beta", "url_field"),
|
new Browser("com.opera.browser.beta", "url_field"),
|
||||||
new Browser("com.opera.gx", "addressbarEdit"),
|
new Browser("com.opera.gx", "addressbarEdit"),
|
||||||
@@ -74,6 +76,7 @@ namespace Bit.Droid.Accessibility
|
|||||||
new Browser("com.opera.touch", "addressbarEdit"),
|
new Browser("com.opera.touch", "addressbarEdit"),
|
||||||
new Browser("com.qflair.browserq", "url"),
|
new Browser("com.qflair.browserq", "url"),
|
||||||
new Browser("com.qwant.liberty", "mozac_browser_toolbar_url_view,url_bar_title"), // 2nd = Legacy (before v4)
|
new Browser("com.qwant.liberty", "mozac_browser_toolbar_url_view,url_bar_title"), // 2nd = Legacy (before v4)
|
||||||
|
new Browser("com.rainsee.create", "search_box"),
|
||||||
new Browser("com.sec.android.app.sbrowser", "location_bar_edit_text"),
|
new Browser("com.sec.android.app.sbrowser", "location_bar_edit_text"),
|
||||||
new Browser("com.sec.android.app.sbrowser.beta", "location_bar_edit_text"),
|
new Browser("com.sec.android.app.sbrowser.beta", "location_bar_edit_text"),
|
||||||
new Browser("com.stoutner.privacybrowser.free", "url_edittext"),
|
new Browser("com.stoutner.privacybrowser.free", "url_edittext"),
|
||||||
@@ -83,6 +86,9 @@ namespace Bit.Droid.Accessibility
|
|||||||
new Browser("com.vivaldi.browser.sopranos", "url_bar"),
|
new Browser("com.vivaldi.browser.sopranos", "url_bar"),
|
||||||
new Browser("com.yandex.browser", "bro_omnibar_address_title_text,bro_omnibox_collapsed_title",
|
new Browser("com.yandex.browser", "bro_omnibar_address_title_text,bro_omnibox_collapsed_title",
|
||||||
(s) => s.Split(new char[]{' ', ' '}).FirstOrDefault()), // 0 = Regular Space, 1 = No-break space (00A0)
|
(s) => s.Split(new char[]{' ', ' '}).FirstOrDefault()), // 0 = Regular Space, 1 = No-break space (00A0)
|
||||||
|
new Browser("com.yjllq.internet", "search_box"),
|
||||||
|
new Browser("com.yjllq.kito", "search_box"),
|
||||||
|
new Browser("com.yujian.ResideMenuDemo", "search_box"),
|
||||||
new Browser("com.z28j.feel", "g2"),
|
new Browser("com.z28j.feel", "g2"),
|
||||||
new Browser("idm.internet.download.manager", "search"),
|
new Browser("idm.internet.download.manager", "search"),
|
||||||
new Browser("idm.internet.download.manager.adm.lite", "search"),
|
new Browser("idm.internet.download.manager.adm.lite", "search"),
|
||||||
@@ -90,6 +96,7 @@ namespace Bit.Droid.Accessibility
|
|||||||
new Browser("io.github.forkmaintainers.iceraven", "mozac_browser_toolbar_url_view"),
|
new Browser("io.github.forkmaintainers.iceraven", "mozac_browser_toolbar_url_view"),
|
||||||
new Browser("mark.via", "am,an"),
|
new Browser("mark.via", "am,an"),
|
||||||
new Browser("mark.via.gp", "as"),
|
new Browser("mark.via.gp", "as"),
|
||||||
|
new Browser("net.dezor.browser", "url_bar"),
|
||||||
new Browser("net.slions.fulguris.full.download", "search"),
|
new Browser("net.slions.fulguris.full.download", "search"),
|
||||||
new Browser("net.slions.fulguris.full.download.debug", "search"),
|
new Browser("net.slions.fulguris.full.download.debug", "search"),
|
||||||
new Browser("net.slions.fulguris.full.playstore", "search"),
|
new Browser("net.slions.fulguris.full.playstore", "search"),
|
||||||
@@ -129,6 +136,7 @@ namespace Bit.Droid.Accessibility
|
|||||||
new Browser("com.htc.sense.browser", "title"),
|
new Browser("com.htc.sense.browser", "title"),
|
||||||
new Browser("com.jerky.browser2", "enterUrl"),
|
new Browser("com.jerky.browser2", "enterUrl"),
|
||||||
new Browser("com.ksmobile.cb", "address_bar_edit_text"),
|
new Browser("com.ksmobile.cb", "address_bar_edit_text"),
|
||||||
|
new Browser("com.lemurbrowser.exts","url_bar"),
|
||||||
new Browser("com.linkbubble.playstore", "url_text"),
|
new Browser("com.linkbubble.playstore", "url_text"),
|
||||||
new Browser("com.mx.browser", "address_editor_with_progress"),
|
new Browser("com.mx.browser", "address_editor_with_progress"),
|
||||||
new Browser("com.mx.browser.tablet", "address_editor_with_progress"),
|
new Browser("com.mx.browser.tablet", "address_editor_with_progress"),
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
||||||
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
|
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
|
||||||
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
|
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
|
||||||
<TargetFrameworkVersion>v12.1</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v13.0</TargetFrameworkVersion>
|
||||||
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
|
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
|
||||||
<NuGetPackageImportStamp>
|
<NuGetPackageImportStamp>
|
||||||
</NuGetPackageImportStamp>
|
</NuGetPackageImportStamp>
|
||||||
@@ -77,12 +77,12 @@
|
|||||||
<PackageReference Include="Portable.BouncyCastle">
|
<PackageReference Include="Portable.BouncyCastle">
|
||||||
<Version>1.9.0</Version>
|
<Version>1.9.0</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.5.1" />
|
<PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.5.1.1" />
|
||||||
<PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.13" />
|
<PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.14" />
|
||||||
<PackageReference Include="Xamarin.AndroidX.CardView" Version="1.0.0.16" />
|
<PackageReference Include="Xamarin.AndroidX.CardView" Version="1.0.0.17" />
|
||||||
<PackageReference Include="Xamarin.AndroidX.Core" Version="1.9.0" />
|
<PackageReference Include="Xamarin.AndroidX.Core" Version="1.9.0.1" />
|
||||||
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.14" />
|
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.15" />
|
||||||
<PackageReference Include="Xamarin.AndroidX.MediaRouter" Version="1.3.1" />
|
<PackageReference Include="Xamarin.AndroidX.MediaRouter" Version="1.3.1.1" />
|
||||||
<PackageReference Include="Xamarin.Essentials">
|
<PackageReference Include="Xamarin.Essentials">
|
||||||
<Version>1.7.3</Version>
|
<Version>1.7.3</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@@ -103,8 +103,10 @@
|
|||||||
<Compile Include="Accessibility\Browser.cs" />
|
<Compile Include="Accessibility\Browser.cs" />
|
||||||
<Compile Include="Accessibility\NodeList.cs" />
|
<Compile Include="Accessibility\NodeList.cs" />
|
||||||
<Compile Include="Accessibility\KnownUsernameField.cs" />
|
<Compile Include="Accessibility\KnownUsernameField.cs" />
|
||||||
|
<Compile Include="Autofill\AutofillConstants.cs" />
|
||||||
<Compile Include="Autofill\AutofillHelpers.cs" />
|
<Compile Include="Autofill\AutofillHelpers.cs" />
|
||||||
<Compile Include="Autofill\AutofillService.cs" />
|
<Compile Include="Autofill\AutofillService.cs" />
|
||||||
|
<Compile Include="Autofill\AutofillExternalSelectionActivity.cs" />
|
||||||
<Compile Include="Autofill\Field.cs" />
|
<Compile Include="Autofill\Field.cs" />
|
||||||
<Compile Include="Autofill\FieldCollection.cs" />
|
<Compile Include="Autofill\FieldCollection.cs" />
|
||||||
<Compile Include="Autofill\FilledItem.cs" />
|
<Compile Include="Autofill\FilledItem.cs" />
|
||||||
@@ -157,6 +159,7 @@
|
|||||||
<Compile Include="Services\AutofillHandler.cs" />
|
<Compile Include="Services\AutofillHandler.cs" />
|
||||||
<Compile Include="Constants.cs" />
|
<Compile Include="Constants.cs" />
|
||||||
<Compile Include="Effects\RemoveFontPaddingEffect.cs" />
|
<Compile Include="Effects\RemoveFontPaddingEffect.cs" />
|
||||||
|
<Compile Include="Services\WatchDeviceService.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidAsset Include="Assets\bwi-font.ttf" />
|
<AndroidAsset Include="Assets\bwi-font.ttf" />
|
||||||
@@ -166,6 +169,10 @@
|
|||||||
<GoogleServicesJson Include="google-services.json" />
|
<GoogleServicesJson Include="google-services.json" />
|
||||||
<GoogleServicesJson Include="google-services.json.enc" />
|
<GoogleServicesJson Include="google-services.json.enc" />
|
||||||
<None Include="fdroid-keystore.jks.enc" />
|
<None Include="fdroid-keystore.jks.enc" />
|
||||||
|
<AndroidNativeLibrary Include="lib\arm64-v8a\libargon2.so" />
|
||||||
|
<AndroidNativeLibrary Include="lib\armeabi-v7a\libargon2.so" />
|
||||||
|
<AndroidNativeLibrary Include="lib\x86\libargon2.so" />
|
||||||
|
<AndroidNativeLibrary Include="lib\x86_64\libargon2.so" />
|
||||||
<None Include="Properties\AndroidManifest.xml" />
|
<None Include="Properties\AndroidManifest.xml" />
|
||||||
<None Include="upload-keystore.jks.enc" />
|
<None Include="upload-keystore.jks.enc" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
10
src/Android/Autofill/AutofillConstants.cs
Normal file
10
src/Android/Autofill/AutofillConstants.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Bit.Droid.Autofill
|
||||||
|
{
|
||||||
|
public class AutofillConstants
|
||||||
|
{
|
||||||
|
public const string AutofillFramework = "autofillFramework";
|
||||||
|
public const string AutofillFrameworkFillType = "autofillFrameworkFillType";
|
||||||
|
public const string AutofillFrameworkUri = "autofillFrameworkUri";
|
||||||
|
public const string AutofillFrameworkCipherId = "autofillFrameworkCipherId";
|
||||||
|
}
|
||||||
|
}
|
||||||
42
src/Android/Autofill/AutofillExternalSelectionActivity.cs
Normal file
42
src/Android/Autofill/AutofillExternalSelectionActivity.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Android.App;
|
||||||
|
using Android.Content.PM;
|
||||||
|
using Android.OS;
|
||||||
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
using Bit.Droid.Utilities;
|
||||||
|
|
||||||
|
namespace Bit.Droid.Autofill
|
||||||
|
{
|
||||||
|
[Activity(
|
||||||
|
NoHistory = true,
|
||||||
|
LaunchMode = LaunchMode.SingleTop)]
|
||||||
|
public class AutofillExternalSelectionActivity : Xamarin.Forms.Platform.Android.FormsAppCompatActivity
|
||||||
|
{
|
||||||
|
protected override void OnCreate(Bundle bundle)
|
||||||
|
{
|
||||||
|
Intent?.Validate();
|
||||||
|
base.OnCreate(bundle);
|
||||||
|
|
||||||
|
var cipherId = Intent?.GetStringExtra(AutofillConstants.AutofillFrameworkCipherId);
|
||||||
|
if (string.IsNullOrEmpty(cipherId))
|
||||||
|
{
|
||||||
|
SetResult(Result.Canceled);
|
||||||
|
Finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GetCipherAndPerformAutofillAsync(cipherId).FireAndForget();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task GetCipherAndPerformAutofillAsync(string cipherId)
|
||||||
|
{
|
||||||
|
var cipherService = ServiceContainer.Resolve<ICipherService>();
|
||||||
|
var cipher = await cipherService.GetAsync(cipherId);
|
||||||
|
var decCipher = await cipher.DecryptAsync();
|
||||||
|
|
||||||
|
var autofillHandler = ServiceContainer.Resolve<IAutofillHandler>();
|
||||||
|
autofillHandler.Autofill(decCipher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,6 +54,7 @@ namespace Bit.Droid.Autofill
|
|||||||
{
|
{
|
||||||
"alook.browser",
|
"alook.browser",
|
||||||
"alook.browser.google",
|
"alook.browser.google",
|
||||||
|
"app.vanadium.browser",
|
||||||
"com.amazon.cloud9",
|
"com.amazon.cloud9",
|
||||||
"com.android.browser",
|
"com.android.browser",
|
||||||
"com.android.chrome",
|
"com.android.chrome",
|
||||||
@@ -78,6 +79,7 @@ namespace Bit.Droid.Autofill
|
|||||||
"com.jamal2367.styx",
|
"com.jamal2367.styx",
|
||||||
"com.kiwibrowser.browser",
|
"com.kiwibrowser.browser",
|
||||||
"com.kiwibrowser.browser.dev",
|
"com.kiwibrowser.browser.dev",
|
||||||
|
"com.lemurbrowser.exts",
|
||||||
"com.microsoft.emmx",
|
"com.microsoft.emmx",
|
||||||
"com.microsoft.emmx.beta",
|
"com.microsoft.emmx.beta",
|
||||||
"com.microsoft.emmx.canary",
|
"com.microsoft.emmx.canary",
|
||||||
@@ -86,6 +88,7 @@ namespace Bit.Droid.Autofill
|
|||||||
"com.mmbox.xbrowser",
|
"com.mmbox.xbrowser",
|
||||||
"com.mycompany.app.soulbrowser",
|
"com.mycompany.app.soulbrowser",
|
||||||
"com.naver.whale",
|
"com.naver.whale",
|
||||||
|
"com.neeva.app",
|
||||||
"com.opera.browser",
|
"com.opera.browser",
|
||||||
"com.opera.browser.beta",
|
"com.opera.browser.beta",
|
||||||
"com.opera.gx",
|
"com.opera.gx",
|
||||||
@@ -94,6 +97,7 @@ namespace Bit.Droid.Autofill
|
|||||||
"com.opera.touch",
|
"com.opera.touch",
|
||||||
"com.qflair.browserq",
|
"com.qflair.browserq",
|
||||||
"com.qwant.liberty",
|
"com.qwant.liberty",
|
||||||
|
"com.rainsee.create",
|
||||||
"com.sec.android.app.sbrowser",
|
"com.sec.android.app.sbrowser",
|
||||||
"com.sec.android.app.sbrowser.beta",
|
"com.sec.android.app.sbrowser.beta",
|
||||||
"com.stoutner.privacybrowser.free",
|
"com.stoutner.privacybrowser.free",
|
||||||
@@ -102,6 +106,9 @@ namespace Bit.Droid.Autofill
|
|||||||
"com.vivaldi.browser.snapshot",
|
"com.vivaldi.browser.snapshot",
|
||||||
"com.vivaldi.browser.sopranos",
|
"com.vivaldi.browser.sopranos",
|
||||||
"com.yandex.browser",
|
"com.yandex.browser",
|
||||||
|
"com.yjllq.internet",
|
||||||
|
"com.yjllq.kito",
|
||||||
|
"com.yujian.ResideMenuDemo",
|
||||||
"com.z28j.feel",
|
"com.z28j.feel",
|
||||||
"idm.internet.download.manager",
|
"idm.internet.download.manager",
|
||||||
"idm.internet.download.manager.adm.lite",
|
"idm.internet.download.manager.adm.lite",
|
||||||
@@ -109,6 +116,7 @@ namespace Bit.Droid.Autofill
|
|||||||
"io.github.forkmaintainers.iceraven",
|
"io.github.forkmaintainers.iceraven",
|
||||||
"mark.via",
|
"mark.via",
|
||||||
"mark.via.gp",
|
"mark.via.gp",
|
||||||
|
"net.dezor.browser",
|
||||||
"net.slions.fulguris.full.download",
|
"net.slions.fulguris.full.download",
|
||||||
"net.slions.fulguris.full.download.debug",
|
"net.slions.fulguris.full.download.debug",
|
||||||
"net.slions.fulguris.full.playstore",
|
"net.slions.fulguris.full.playstore",
|
||||||
@@ -207,7 +215,7 @@ namespace Bit.Droid.Autofill
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var dataset = BuildDataset(parser.ApplicationContext, parser.FieldCollection, items[i],
|
var dataset = BuildDataset(parser.ApplicationContext, parser.FieldCollection, items[i],
|
||||||
inlinePresentationSpec);
|
true, inlinePresentationSpec);
|
||||||
if (dataset != null)
|
if (dataset != null)
|
||||||
{
|
{
|
||||||
responseBuilder.AddDataset(dataset);
|
responseBuilder.AddDataset(dataset);
|
||||||
@@ -221,7 +229,7 @@ namespace Bit.Droid.Autofill
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Dataset BuildDataset(Context context, FieldCollection fields, FilledItem filledItem,
|
public static Dataset BuildDataset(Context context, FieldCollection fields, FilledItem filledItem,
|
||||||
InlinePresentationSpec inlinePresentationSpec = null)
|
bool includeAuthIntent, InlinePresentationSpec inlinePresentationSpec = null)
|
||||||
{
|
{
|
||||||
var overlayPresentation = BuildOverlayPresentation(
|
var overlayPresentation = BuildOverlayPresentation(
|
||||||
filledItem.Name,
|
filledItem.Name,
|
||||||
@@ -242,6 +250,15 @@ namespace Bit.Droid.Autofill
|
|||||||
{
|
{
|
||||||
datasetBuilder.SetInlinePresentation(inlinePresentation);
|
datasetBuilder.SetInlinePresentation(inlinePresentation);
|
||||||
}
|
}
|
||||||
|
if (includeAuthIntent)
|
||||||
|
{
|
||||||
|
var intent = new Intent(context, typeof(AutofillExternalSelectionActivity));
|
||||||
|
intent.PutExtra(AutofillConstants.AutofillFramework, true);
|
||||||
|
intent.PutExtra(AutofillConstants.AutofillFrameworkCipherId, filledItem.Id);
|
||||||
|
var pendingIntent = PendingIntent.GetActivity(context, ++_pendingIntentId, intent,
|
||||||
|
AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.CancelCurrent, true));
|
||||||
|
datasetBuilder.SetAuthentication(pendingIntent?.IntentSender);
|
||||||
|
}
|
||||||
if (filledItem.ApplyToFields(fields, datasetBuilder))
|
if (filledItem.ApplyToFields(fields, datasetBuilder))
|
||||||
{
|
{
|
||||||
return datasetBuilder.Build();
|
return datasetBuilder.Build();
|
||||||
@@ -253,25 +270,26 @@ namespace Bit.Droid.Autofill
|
|||||||
IList<InlinePresentationSpec> inlinePresentationSpecs = null)
|
IList<InlinePresentationSpec> inlinePresentationSpecs = null)
|
||||||
{
|
{
|
||||||
var intent = new Intent(context, typeof(MainActivity));
|
var intent = new Intent(context, typeof(MainActivity));
|
||||||
intent.PutExtra("autofillFramework", true);
|
intent.PutExtra(AutofillConstants.AutofillFramework, true);
|
||||||
if (fields.FillableForLogin)
|
if (fields.FillableForLogin)
|
||||||
{
|
{
|
||||||
intent.PutExtra("autofillFrameworkFillType", (int)CipherType.Login);
|
intent.PutExtra(AutofillConstants.AutofillFrameworkFillType, (int)CipherType.Login);
|
||||||
}
|
}
|
||||||
else if (fields.FillableForCard)
|
else if (fields.FillableForCard)
|
||||||
{
|
{
|
||||||
intent.PutExtra("autofillFrameworkFillType", (int)CipherType.Card);
|
intent.PutExtra(AutofillConstants.AutofillFrameworkFillType, (int)CipherType.Card);
|
||||||
}
|
}
|
||||||
else if (fields.FillableForIdentity)
|
else if (fields.FillableForIdentity)
|
||||||
{
|
{
|
||||||
intent.PutExtra("autofillFrameworkFillType", (int)CipherType.Identity);
|
intent.PutExtra(AutofillConstants.AutofillFrameworkFillType, (int)CipherType.Identity);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
intent.PutExtra("autofillFrameworkUri", uri);
|
intent.PutExtra(AutofillConstants.AutofillFrameworkUri, uri);
|
||||||
var pendingIntent = PendingIntent.GetActivity(context, ++_pendingIntentId, intent, AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.CancelCurrent, true));
|
var pendingIntent = PendingIntent.GetActivity(context, ++_pendingIntentId, intent,
|
||||||
|
AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.CancelCurrent, true));
|
||||||
|
|
||||||
var overlayPresentation = BuildOverlayPresentation(
|
var overlayPresentation = BuildOverlayPresentation(
|
||||||
AppResources.AutofillWithBitwarden,
|
AppResources.AutofillWithBitwarden,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace Bit.Droid.Autofill
|
|||||||
private List<Field> _passwordFields = null;
|
private List<Field> _passwordFields = null;
|
||||||
private List<Field> _usernameFields = null;
|
private List<Field> _usernameFields = null;
|
||||||
private HashSet<string> _ignoreSearchTerms = new HashSet<string> { "search", "find", "recipient", "edit" };
|
private HashSet<string> _ignoreSearchTerms = new HashSet<string> { "search", "find", "recipient", "edit" };
|
||||||
|
private HashSet<string> _usernameTerms = new HashSet<string> { "email", "phone", "username"};
|
||||||
private HashSet<string> _passwordTerms = new HashSet<string> { "password", "pswd" };
|
private HashSet<string> _passwordTerms = new HashSet<string> { "password", "pswd" };
|
||||||
|
|
||||||
public List<AutofillId> AutofillIds { get; private set; } = new List<AutofillId>();
|
public List<AutofillId> AutofillIds { get; private set; } = new List<AutofillId>();
|
||||||
@@ -98,6 +99,11 @@ namespace Bit.Droid.Autofill
|
|||||||
_usernameFields.Add(usernameField);
|
_usernameFields.Add(usernameField);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_usernameFields.Any())
|
||||||
|
{
|
||||||
|
_usernameFields = Fields.Where(f => FieldIsUsername(f)).ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return _usernameFields;
|
return _usernameFields;
|
||||||
}
|
}
|
||||||
@@ -321,13 +327,23 @@ namespace Bit.Droid.Autofill
|
|||||||
}
|
}
|
||||||
|
|
||||||
return inputTypePassword && !ValueContainsAnyTerms(f.IdEntry, _ignoreSearchTerms) &&
|
return inputTypePassword && !ValueContainsAnyTerms(f.IdEntry, _ignoreSearchTerms) &&
|
||||||
!ValueContainsAnyTerms(f.Hint, _ignoreSearchTerms);
|
!ValueContainsAnyTerms(f.Hint, _ignoreSearchTerms) && !FieldIsUsername(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool FieldHasPasswordTerms(Field f)
|
private bool FieldHasPasswordTerms(Field f)
|
||||||
{
|
{
|
||||||
return ValueContainsAnyTerms(f.IdEntry, _passwordTerms) || ValueContainsAnyTerms(f.Hint, _passwordTerms);
|
return ValueContainsAnyTerms(f.IdEntry, _passwordTerms) || ValueContainsAnyTerms(f.Hint, _passwordTerms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool FieldIsUsername(Field f)
|
||||||
|
{
|
||||||
|
return f.InputType.HasFlag(InputTypes.TextVariationWebEmailAddress) || FieldHasUsernameTerms(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool FieldHasUsernameTerms(Field f)
|
||||||
|
{
|
||||||
|
return ValueContainsAnyTerms(f.IdEntry, _usernameTerms) || ValueContainsAnyTerms(f.Hint, _usernameTerms);
|
||||||
|
}
|
||||||
|
|
||||||
private bool ValueContainsAnyTerms(string value, HashSet<string> terms)
|
private bool ValueContainsAnyTerms(string value, HashSet<string> terms)
|
||||||
{
|
{
|
||||||
@@ -339,4 +355,4 @@ namespace Bit.Droid.Autofill
|
|||||||
return terms.Any(t => lowerValue.Contains(t));
|
return terms.Any(t => lowerValue.Contains(t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ namespace Bit.Droid.Autofill
|
|||||||
|
|
||||||
public FilledItem(CipherView cipher)
|
public FilledItem(CipherView cipher)
|
||||||
{
|
{
|
||||||
|
Id = cipher.Id;
|
||||||
Name = cipher.Name;
|
Name = cipher.Name;
|
||||||
Type = cipher.Type;
|
Type = cipher.Type;
|
||||||
Subtitle = cipher.SubTitle;
|
Subtitle = cipher.SubTitle;
|
||||||
@@ -55,6 +56,7 @@ namespace Bit.Droid.Autofill
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Id { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Subtitle { get; set; } = string.Empty;
|
public string Subtitle { get; set; } = string.Empty;
|
||||||
public int Icon { get; set; } = Resource.Drawable.login;
|
public int Icon { get; set; } = Resource.Drawable.login;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ using Bit.Core;
|
|||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
using Bit.Droid.Autofill;
|
||||||
using Bit.Droid.Receivers;
|
using Bit.Droid.Receivers;
|
||||||
using Bit.Droid.Utilities;
|
using Bit.Droid.Utilities;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@@ -322,13 +323,13 @@ namespace Bit.Droid
|
|||||||
{
|
{
|
||||||
var options = new AppOptions
|
var options = new AppOptions
|
||||||
{
|
{
|
||||||
Uri = Intent.GetStringExtra("uri") ?? Intent.GetStringExtra("autofillFrameworkUri"),
|
Uri = Intent.GetStringExtra("uri") ?? Intent.GetStringExtra(AutofillConstants.AutofillFrameworkUri),
|
||||||
MyVaultTile = Intent.GetBooleanExtra("myVaultTile", false),
|
MyVaultTile = Intent.GetBooleanExtra("myVaultTile", false),
|
||||||
GeneratorTile = Intent.GetBooleanExtra("generatorTile", false),
|
GeneratorTile = Intent.GetBooleanExtra("generatorTile", false),
|
||||||
FromAutofillFramework = Intent.GetBooleanExtra("autofillFramework", false),
|
FromAutofillFramework = Intent.GetBooleanExtra(AutofillConstants.AutofillFramework, false),
|
||||||
CreateSend = GetCreateSendRequest(Intent)
|
CreateSend = GetCreateSendRequest(Intent)
|
||||||
};
|
};
|
||||||
var fillType = Intent.GetIntExtra("autofillFrameworkFillType", 0);
|
var fillType = Intent.GetIntExtra(AutofillConstants.AutofillFrameworkFillType, 0);
|
||||||
if (fillType > 0)
|
if (fillType > 0)
|
||||||
{
|
{
|
||||||
options.FillType = (CipherType)fillType;
|
options.FillType = (CipherType)fillType;
|
||||||
|
|||||||
@@ -45,9 +45,16 @@ namespace Bit.Droid
|
|||||||
if (ServiceContainer.RegisteredServices.Count == 0)
|
if (ServiceContainer.RegisteredServices.Count == 0)
|
||||||
{
|
{
|
||||||
RegisterLocalServices();
|
RegisterLocalServices();
|
||||||
|
|
||||||
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||||
ServiceContainer.Init(deviceActionService.DeviceUserAgent, Core.Constants.ClearCiphersCacheKey,
|
ServiceContainer.Init(deviceActionService.DeviceUserAgent, Core.Constants.ClearCiphersCacheKey,
|
||||||
Core.Constants.AndroidAllClearCipherCacheKeys);
|
Core.Constants.AndroidAllClearCipherCacheKeys);
|
||||||
|
|
||||||
|
ServiceContainer.Register<IWatchDeviceService>(new WatchDeviceService(ServiceContainer.Resolve<ICipherService>(),
|
||||||
|
ServiceContainer.Resolve<IEnvironmentService>(),
|
||||||
|
ServiceContainer.Resolve<IStateService>(),
|
||||||
|
ServiceContainer.Resolve<IVaultTimeoutService>()));
|
||||||
|
|
||||||
InitializeAppSetup();
|
InitializeAppSetup();
|
||||||
|
|
||||||
// TODO: Update when https://github.com/bitwarden/mobile/pull/1662 gets merged
|
// TODO: Update when https://github.com/bitwarden/mobile/pull/1662 gets merged
|
||||||
@@ -73,8 +80,9 @@ namespace Bit.Droid
|
|||||||
ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"),
|
ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"),
|
||||||
ServiceContainer.Resolve<IAuthService>("authService"),
|
ServiceContainer.Resolve<IAuthService>("authService"),
|
||||||
ServiceContainer.Resolve<ILogger>("logger"),
|
ServiceContainer.Resolve<ILogger>("logger"),
|
||||||
ServiceContainer.Resolve<IMessagingService>("messagingService"));
|
ServiceContainer.Resolve<IMessagingService>("messagingService"),
|
||||||
ServiceContainer.Register<IAccountsManager>("accountsManager", accountsManager);
|
ServiceContainer.Resolve<IWatchDeviceService>());
|
||||||
|
ServiceContainer.Register<IAccountsManager>("accountsManager", accountsManager);
|
||||||
}
|
}
|
||||||
#if !FDROID
|
#if !FDROID
|
||||||
if (Build.VERSION.SdkInt <= BuildVersionCodes.Kitkat)
|
if (Build.VERSION.SdkInt <= BuildVersionCodes.Kitkat)
|
||||||
@@ -141,9 +149,10 @@ namespace Bit.Droid
|
|||||||
var clipboardService = new ClipboardService(stateService);
|
var clipboardService = new ClipboardService(stateService);
|
||||||
var deviceActionService = new DeviceActionService(stateService, messagingService);
|
var deviceActionService = new DeviceActionService(stateService, messagingService);
|
||||||
var fileService = new FileService(stateService, broadcasterService);
|
var fileService = new FileService(stateService, broadcasterService);
|
||||||
var autofillHandler = new AutofillHandler(stateService, messagingService, clipboardService, new LazyResolve<IEventService>());
|
|
||||||
var platformUtilsService = new MobilePlatformUtilsService(deviceActionService, clipboardService,
|
var platformUtilsService = new MobilePlatformUtilsService(deviceActionService, clipboardService,
|
||||||
messagingService, broadcasterService);
|
messagingService, broadcasterService);
|
||||||
|
var autofillHandler = new AutofillHandler(stateService, messagingService, clipboardService,
|
||||||
|
platformUtilsService, new LazyResolve<IEventService>());
|
||||||
var biometricService = new BiometricService();
|
var biometricService = new BiometricService();
|
||||||
var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService);
|
var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService);
|
||||||
var cryptoService = new CryptoService(stateService, cryptoFunctionService);
|
var cryptoService = new CryptoService(stateService, cryptoFunctionService);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2022.10.1" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2023.1.1" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="32" />
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.NFC" />
|
<uses-permission android:name="android.permission.NFC" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
@@ -40,10 +40,16 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
<!-- Package visibility (for Android 11+) -->
|
<!-- Support for Xamarin.Essentials.Browser.OpenAsync (for Android > 11) -->
|
||||||
|
<!-- Related docs: https://learn.microsoft.com/en-us/xamarin/essentials/open-browser?tabs=android -->
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="*" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<data android:scheme="http"/>
|
||||||
|
</intent>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<data android:scheme="https"/>
|
||||||
</intent>
|
</intent>
|
||||||
</queries>
|
</queries>
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using Android.Content;
|
using Android.Content;
|
||||||
|
using Android.OS;
|
||||||
|
|
||||||
namespace Bit.Droid.Receivers
|
namespace Bit.Droid.Receivers
|
||||||
{
|
{
|
||||||
@@ -8,7 +9,17 @@ namespace Bit.Droid.Receivers
|
|||||||
public override void OnReceive(Context context, Intent intent)
|
public override void OnReceive(Context context, Intent intent)
|
||||||
{
|
{
|
||||||
var clipboardManager = context.GetSystemService(Context.ClipboardService) as ClipboardManager;
|
var clipboardManager = context.GetSystemService(Context.ClipboardService) as ClipboardManager;
|
||||||
clipboardManager.PrimaryClip = ClipData.NewPlainText("bitwarden", " ");
|
if (clipboardManager == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// ClearPrimaryClip is supported down to API 28 with mixed results, so we're requiring 33+ instead
|
||||||
|
if ((int)Build.VERSION.SdkInt < 33)
|
||||||
|
{
|
||||||
|
clipboardManager.PrimaryClip = ClipData.NewPlainText("bitwarden", " ");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clipboardManager.ClearPrimaryClip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ namespace Bit.Droid.Renderers
|
|||||||
}
|
}
|
||||||
if (Control != null)
|
if (Control != null)
|
||||||
{
|
{
|
||||||
|
Control.SetHintTextColor(ThemeHelpers.MutedColor);
|
||||||
var t = ResourcesCompat.GetDrawable(Resources, Resource.Drawable.switch_thumb, null);
|
var t = ResourcesCompat.GetDrawable(Resources, Resource.Drawable.switch_thumb, null);
|
||||||
if (t is GradientDrawable thumb)
|
if (t is GradientDrawable thumb)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,6 +17,9 @@
|
|||||||
<compatibility-package
|
<compatibility-package
|
||||||
android:name="alook.browser.google"
|
android:name="alook.browser.google"
|
||||||
android:maxLongVersionCode="10000000000"/>
|
android:maxLongVersionCode="10000000000"/>
|
||||||
|
<compatibility-package
|
||||||
|
android:name="app.vanadium.browser"
|
||||||
|
android:maxLongVersionCode="10000000000"/>
|
||||||
<compatibility-package
|
<compatibility-package
|
||||||
android:name="com.amazon.cloud9"
|
android:name="com.amazon.cloud9"
|
||||||
android:maxLongVersionCode="10000000000"/>
|
android:maxLongVersionCode="10000000000"/>
|
||||||
@@ -89,6 +92,9 @@
|
|||||||
<compatibility-package
|
<compatibility-package
|
||||||
android:name="com.kiwibrowser.browser.dev"
|
android:name="com.kiwibrowser.browser.dev"
|
||||||
android:maxLongVersionCode="10000000000"/>
|
android:maxLongVersionCode="10000000000"/>
|
||||||
|
<compatibility-package
|
||||||
|
android:name="com.lemurbrowser.exts"
|
||||||
|
android:maxLongVersionCode="10000000000"/>
|
||||||
<compatibility-package
|
<compatibility-package
|
||||||
android:name="com.microsoft.emmx"
|
android:name="com.microsoft.emmx"
|
||||||
android:maxLongVersionCode="10000000000"/>
|
android:maxLongVersionCode="10000000000"/>
|
||||||
@@ -113,6 +119,9 @@
|
|||||||
<compatibility-package
|
<compatibility-package
|
||||||
android:name="com.naver.whale"
|
android:name="com.naver.whale"
|
||||||
android:maxLongVersionCode="10000000000"/>
|
android:maxLongVersionCode="10000000000"/>
|
||||||
|
<compatibility-package
|
||||||
|
android:name="com.neeva.app"
|
||||||
|
android:maxLongVersionCode="10000000000"/>
|
||||||
<compatibility-package
|
<compatibility-package
|
||||||
android:name="com.opera.browser"
|
android:name="com.opera.browser"
|
||||||
android:maxLongVersionCode="10000000000"/>
|
android:maxLongVersionCode="10000000000"/>
|
||||||
@@ -137,6 +146,9 @@
|
|||||||
<compatibility-package
|
<compatibility-package
|
||||||
android:name="com.qwant.liberty"
|
android:name="com.qwant.liberty"
|
||||||
android:maxLongVersionCode="10000000000"/>
|
android:maxLongVersionCode="10000000000"/>
|
||||||
|
<compatibility-package
|
||||||
|
android:name="com.rainsee.create"
|
||||||
|
android:maxLongVersionCode="10000000000"/>
|
||||||
<compatibility-package
|
<compatibility-package
|
||||||
android:name="com.sec.android.app.sbrowser"
|
android:name="com.sec.android.app.sbrowser"
|
||||||
android:maxLongVersionCode="10000000000"/>
|
android:maxLongVersionCode="10000000000"/>
|
||||||
@@ -161,6 +173,15 @@
|
|||||||
<compatibility-package
|
<compatibility-package
|
||||||
android:name="com.yandex.browser"
|
android:name="com.yandex.browser"
|
||||||
android:maxLongVersionCode="10000000000"/>
|
android:maxLongVersionCode="10000000000"/>
|
||||||
|
<compatibility-package
|
||||||
|
android:name="com.yjllq.internet"
|
||||||
|
android:maxLongVersionCode="10000000000"/>
|
||||||
|
<compatibility-package
|
||||||
|
android:name="com.yjllq.kito"
|
||||||
|
android:maxLongVersionCode="10000000000"/>
|
||||||
|
<compatibility-package
|
||||||
|
android:name="com.yujian.ResideMenuDemo"
|
||||||
|
android:maxLongVersionCode="10000000000"/>
|
||||||
<compatibility-package
|
<compatibility-package
|
||||||
android:name="com.z28j.feel"
|
android:name="com.z28j.feel"
|
||||||
android:maxLongVersionCode="10000000000"/>
|
android:maxLongVersionCode="10000000000"/>
|
||||||
@@ -182,6 +203,9 @@
|
|||||||
<compatibility-package
|
<compatibility-package
|
||||||
android:name="mark.via.gp"
|
android:name="mark.via.gp"
|
||||||
android:maxLongVersionCode="10000000000"/>
|
android:maxLongVersionCode="10000000000"/>
|
||||||
|
<compatibility-package
|
||||||
|
android:name="net.dezor.browser"
|
||||||
|
android:maxLongVersionCode="10000000000"/>
|
||||||
<compatibility-package
|
<compatibility-package
|
||||||
android:name="net.slions.fulguris.full.download"
|
android:name="net.slions.fulguris.full.download"
|
||||||
android:maxLongVersionCode="10000000000"/>
|
android:maxLongVersionCode="10000000000"/>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Android.Content;
|
|||||||
using Android.OS;
|
using Android.OS;
|
||||||
using Android.Provider;
|
using Android.Provider;
|
||||||
using Android.Views.Autofill;
|
using Android.Views.Autofill;
|
||||||
|
using Bit.App.Resources;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Models.View;
|
using Bit.Core.Models.View;
|
||||||
@@ -20,16 +21,19 @@ namespace Bit.Droid.Services
|
|||||||
private readonly IStateService _stateService;
|
private readonly IStateService _stateService;
|
||||||
private readonly IMessagingService _messagingService;
|
private readonly IMessagingService _messagingService;
|
||||||
private readonly IClipboardService _clipboardService;
|
private readonly IClipboardService _clipboardService;
|
||||||
|
private readonly IPlatformUtilsService _platformUtilsService;
|
||||||
private readonly LazyResolve<IEventService> _eventService;
|
private readonly LazyResolve<IEventService> _eventService;
|
||||||
|
|
||||||
public AutofillHandler(IStateService stateService,
|
public AutofillHandler(IStateService stateService,
|
||||||
IMessagingService messagingService,
|
IMessagingService messagingService,
|
||||||
IClipboardService clipboardService,
|
IClipboardService clipboardService,
|
||||||
|
IPlatformUtilsService platformUtilsService,
|
||||||
LazyResolve<IEventService> eventService)
|
LazyResolve<IEventService> eventService)
|
||||||
{
|
{
|
||||||
_stateService = stateService;
|
_stateService = stateService;
|
||||||
_messagingService = messagingService;
|
_messagingService = messagingService;
|
||||||
_clipboardService = clipboardService;
|
_clipboardService = clipboardService;
|
||||||
|
_platformUtilsService = platformUtilsService;
|
||||||
_eventService = eventService;
|
_eventService = eventService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,12 +77,12 @@ namespace Bit.Droid.Services
|
|||||||
|
|
||||||
public void Autofill(CipherView cipher)
|
public void Autofill(CipherView cipher)
|
||||||
{
|
{
|
||||||
var activity = (MainActivity)CrossCurrentActivity.Current.Activity;
|
var activity = CrossCurrentActivity.Current.Activity as Xamarin.Forms.Platform.Android.FormsAppCompatActivity;
|
||||||
if (activity == null)
|
if (activity == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (activity.Intent?.GetBooleanExtra("autofillFramework", false) ?? false)
|
if (activity.Intent?.GetBooleanExtra(AutofillConstants.AutofillFramework, false) ?? false)
|
||||||
{
|
{
|
||||||
if (cipher == null)
|
if (cipher == null)
|
||||||
{
|
{
|
||||||
@@ -103,7 +107,7 @@ namespace Bit.Droid.Services
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var task = CopyTotpAsync(cipher);
|
var task = CopyTotpAsync(cipher);
|
||||||
var dataset = AutofillHelpers.BuildDataset(activity, parser.FieldCollection, new FilledItem(cipher));
|
var dataset = AutofillHelpers.BuildDataset(activity, parser.FieldCollection, new FilledItem(cipher), false);
|
||||||
var replyIntent = new Intent();
|
var replyIntent = new Intent();
|
||||||
replyIntent.PutExtra(AutofillManager.ExtraAuthenticationResult, dataset);
|
replyIntent.PutExtra(AutofillManager.ExtraAuthenticationResult, dataset);
|
||||||
activity.SetResult(Result.Ok, replyIntent);
|
activity.SetResult(Result.Ok, replyIntent);
|
||||||
@@ -202,6 +206,7 @@ namespace Bit.Droid.Services
|
|||||||
if (totp != null)
|
if (totp != null)
|
||||||
{
|
{
|
||||||
await _clipboardService.CopyTextAsync(totp);
|
await _clipboardService.CopyTextAsync(totp);
|
||||||
|
_platformUtilsService.ShowToastForCopiedValue(AppResources.VerificationCodeTotp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using Android.OS;
|
|||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Droid.Receivers;
|
using Bit.Droid.Receivers;
|
||||||
using Bit.Droid.Utilities;
|
using Bit.Droid.Utilities;
|
||||||
using Plugin.CurrentActivity;
|
|
||||||
using Xamarin.Essentials;
|
using Xamarin.Essentials;
|
||||||
|
|
||||||
namespace Bit.Droid.Services
|
namespace Bit.Droid.Services
|
||||||
@@ -21,9 +20,9 @@ namespace Bit.Droid.Services
|
|||||||
_stateService = stateService;
|
_stateService = stateService;
|
||||||
|
|
||||||
_clearClipboardPendingIntent = new Lazy<PendingIntent>(() =>
|
_clearClipboardPendingIntent = new Lazy<PendingIntent>(() =>
|
||||||
PendingIntent.GetBroadcast(CrossCurrentActivity.Current.Activity,
|
PendingIntent.GetBroadcast(Application.Context,
|
||||||
0,
|
0,
|
||||||
new Intent(CrossCurrentActivity.Current.Activity, typeof(ClearClipboardAlarmReceiver)),
|
new Intent(Application.Context, typeof(ClearClipboardAlarmReceiver)),
|
||||||
AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.UpdateCurrent, false)));
|
AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.UpdateCurrent, false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +44,7 @@ namespace Bit.Droid.Services
|
|||||||
}
|
}
|
||||||
catch (Java.Lang.SecurityException ex) when (ex.Message.Contains("does not belong to"))
|
catch (Java.Lang.SecurityException ex) when (ex.Message.Contains("does not belong to"))
|
||||||
{
|
{
|
||||||
// #1962 Just ignore, the content is copied either way but there is some app interfiering in the process
|
// #1962 Just ignore, the content is copied either way but there is some app interfering in the process
|
||||||
// that the OS catches and just throws this exception.
|
// that the OS catches and just throws this exception.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,9 +57,7 @@ namespace Bit.Droid.Services
|
|||||||
|
|
||||||
private void CopyToClipboard(string text, bool isSensitive = true)
|
private void CopyToClipboard(string text, bool isSensitive = true)
|
||||||
{
|
{
|
||||||
var activity = (MainActivity)CrossCurrentActivity.Current.Activity;
|
var clipboardManager = Application.Context.GetSystemService(Context.ClipboardService) as ClipboardManager;
|
||||||
var clipboardManager = activity.GetSystemService(
|
|
||||||
Context.ClipboardService) as Android.Content.ClipboardManager;
|
|
||||||
var clipData = ClipData.NewPlainText("bitwarden", text);
|
var clipData = ClipData.NewPlainText("bitwarden", text);
|
||||||
if (isSensitive)
|
if (isSensitive)
|
||||||
{
|
{
|
||||||
@@ -87,7 +84,7 @@ namespace Bit.Droid.Services
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var triggerMs = Java.Lang.JavaSystem.CurrentTimeMillis() + clearMs;
|
var triggerMs = Java.Lang.JavaSystem.CurrentTimeMillis() + clearMs;
|
||||||
var alarmManager = CrossCurrentActivity.Current.Activity.GetSystemService(Context.AlarmService) as AlarmManager;
|
var alarmManager = Application.Context.GetSystemService(Context.AlarmService) as AlarmManager;
|
||||||
alarmManager.Set(AlarmType.Rtc, triggerMs, _clearClipboardPendingIntent.Value);
|
alarmManager.Set(AlarmType.Rtc, triggerMs, _clearClipboardPendingIntent.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ using Org.BouncyCastle.Crypto.Digests;
|
|||||||
using Org.BouncyCastle.Crypto.Generators;
|
using Org.BouncyCastle.Crypto.Generators;
|
||||||
using Org.BouncyCastle.Crypto.Parameters;
|
using Org.BouncyCastle.Crypto.Parameters;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Java.Lang;
|
||||||
|
|
||||||
namespace Bit.Droid.Services
|
namespace Bit.Droid.Services
|
||||||
{
|
{
|
||||||
@@ -33,5 +35,19 @@ namespace Bit.Droid.Services
|
|||||||
generator.Init(password, salt, iterations);
|
generator.Init(password, salt, iterations);
|
||||||
return ((KeyParameter)generator.GenerateDerivedMacParameters(keySize)).GetKey();
|
return ((KeyParameter)generator.GenerateDerivedMacParameters(keySize)).GetKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] Argon2id(byte[] password, byte[] salt, int iterations, int memory, int parallelism)
|
||||||
|
{
|
||||||
|
JavaSystem.LoadLibrary("argon2");
|
||||||
|
int keySize = 32;
|
||||||
|
var key = new byte[keySize];
|
||||||
|
argon2id_hash_raw(iterations, memory, parallelism,
|
||||||
|
password, password.Length, salt, salt.Length, key, key.Length);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("argon2", EntryPoint = "argon2id_hash_raw")]
|
||||||
|
private static extern int argon2id_hash_raw(int timeCost, int memoryCost, int parallelism,
|
||||||
|
byte[] pwd, int pwdlen, byte[] salt, int saltlen, byte[] hash, int hashlen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ using Bit.Core.Enums;
|
|||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Bit.Droid.Utilities;
|
using Bit.Droid.Utilities;
|
||||||
using Plugin.CurrentActivity;
|
using Plugin.CurrentActivity;
|
||||||
|
using static Bit.App.Pages.SettingsPageViewModel;
|
||||||
|
|
||||||
namespace Bit.Droid.Services
|
namespace Bit.Droid.Services
|
||||||
{
|
{
|
||||||
@@ -69,14 +70,17 @@ namespace Bit.Droid.Services
|
|||||||
|
|
||||||
public bool LaunchApp(string appName)
|
public bool LaunchApp(string appName)
|
||||||
{
|
{
|
||||||
|
if ((int)Build.VERSION.SdkInt < 33)
|
||||||
|
{
|
||||||
|
// API 33 required to avoid using wildcard app visibility or dangerous permissions
|
||||||
|
// https://developer.android.com/reference/android/content/pm/PackageManager#getLaunchIntentSenderForPackage(java.lang.String)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
var activity = CrossCurrentActivity.Current.Activity;
|
var activity = CrossCurrentActivity.Current.Activity;
|
||||||
appName = appName.Replace("androidapp://", string.Empty);
|
appName = appName.Replace("androidapp://", string.Empty);
|
||||||
var launchIntent = activity.PackageManager.GetLaunchIntentForPackage(appName);
|
var launchIntentSender = activity?.PackageManager?.GetLaunchIntentSenderForPackage(appName);
|
||||||
if (launchIntent != null)
|
launchIntentSender?.SendIntent(activity, Result.Ok, null, null, null);
|
||||||
{
|
return launchIntentSender != null;
|
||||||
activity.StartActivity(launchIntent);
|
|
||||||
}
|
|
||||||
return launchIntent != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ShowLoadingAsync(string text)
|
public async Task ShowLoadingAsync(string text)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Models;
|
using Bit.App.Models;
|
||||||
@@ -25,13 +26,13 @@ namespace Bit.Droid.Services
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var fallback = ToDotnetFallbackLanguage(new PlatformCulture(netLanguage));
|
var fallback = ToDotnetFallbackLanguage(new PlatformCulture(netLanguage));
|
||||||
Console.WriteLine(netLanguage + " failed, trying " + fallback + " (" + e1.Message + ")");
|
Debug.WriteLine(netLanguage + " failed, trying " + fallback + " (" + e1.Message + ")");
|
||||||
ci = new CultureInfo(fallback);
|
ci = new CultureInfo(fallback);
|
||||||
}
|
}
|
||||||
catch (CultureNotFoundException e2)
|
catch (CultureNotFoundException e2)
|
||||||
{
|
{
|
||||||
// iOS language not valid .NET culture, falling back to English
|
// iOS language not valid .NET culture, falling back to English
|
||||||
Console.WriteLine(netLanguage + " couldn't be set, using 'en' (" + e2.Message + ")");
|
Debug.WriteLine(netLanguage + " couldn't be set, using 'en' (" + e2.Message + ")");
|
||||||
ci = new CultureInfo("en");
|
ci = new CultureInfo("en");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,7 +41,7 @@ namespace Bit.Droid.Services
|
|||||||
|
|
||||||
private string AndroidToDotnetLanguage(string androidLanguage)
|
private string AndroidToDotnetLanguage(string androidLanguage)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Android Language:" + androidLanguage);
|
Debug.WriteLine("Android Language:" + androidLanguage);
|
||||||
var netLanguage = androidLanguage;
|
var netLanguage = androidLanguage;
|
||||||
if (androidLanguage.StartsWith("zh"))
|
if (androidLanguage.StartsWith("zh"))
|
||||||
{
|
{
|
||||||
@@ -79,13 +80,13 @@ namespace Bit.Droid.Services
|
|||||||
// ONLY use cultures that have been tested and known to work
|
// ONLY use cultures that have been tested and known to work
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Console.WriteLine(".NET Language/Locale:" + netLanguage);
|
Debug.WriteLine(".NET Language/Locale:" + netLanguage);
|
||||||
return netLanguage;
|
return netLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ToDotnetFallbackLanguage(PlatformCulture platCulture)
|
private string ToDotnetFallbackLanguage(PlatformCulture platCulture)
|
||||||
{
|
{
|
||||||
Console.WriteLine(".NET Fallback Language:" + platCulture.LanguageCode);
|
Debug.WriteLine(".NET Fallback Language:" + platCulture.LanguageCode);
|
||||||
var netLanguage = platCulture.LanguageCode; // use the first part of the identifier (two chars, usually);
|
var netLanguage = platCulture.LanguageCode; // use the first part of the identifier (two chars, usually);
|
||||||
switch (platCulture.LanguageCode)
|
switch (platCulture.LanguageCode)
|
||||||
{
|
{
|
||||||
@@ -95,7 +96,7 @@ namespace Bit.Droid.Services
|
|||||||
// add more application-specific cases here (if required)
|
// add more application-specific cases here (if required)
|
||||||
// ONLY use cultures that have been tested and known to work
|
// ONLY use cultures that have been tested and known to work
|
||||||
}
|
}
|
||||||
Console.WriteLine(".NET Fallback Language/Locale:" + netLanguage + " (application-specific)");
|
Debug.WriteLine(".NET Fallback Language/Locale:" + netLanguage + " (application-specific)");
|
||||||
return netLanguage;
|
return netLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
29
src/Android/Services/WatchDeviceService.cs
Normal file
29
src/Android/Services/WatchDeviceService.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Bit.App.Services;
|
||||||
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Models;
|
||||||
|
|
||||||
|
namespace Bit.Droid.Services
|
||||||
|
{
|
||||||
|
public class WatchDeviceService : BaseWatchDeviceService
|
||||||
|
{
|
||||||
|
public WatchDeviceService(ICipherService cipherService,
|
||||||
|
IEnvironmentService environmentService,
|
||||||
|
IStateService stateService,
|
||||||
|
IVaultTimeoutService vaultTimeoutService)
|
||||||
|
: base(cipherService, environmentService, stateService, vaultTimeoutService)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool IsSupported => false;
|
||||||
|
|
||||||
|
public override bool IsConnected => false;
|
||||||
|
|
||||||
|
protected override bool CanSendData => false;
|
||||||
|
|
||||||
|
protected override Task SendDataToWatchAsync(WatchDTO watchDto) => throw new NotImplementedException();
|
||||||
|
|
||||||
|
protected override void ConnectToWatch() => throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,7 +62,7 @@ namespace Bit.Droid.Utilities
|
|||||||
theme = ThemeManager.Dark;
|
theme = ThemeManager.Dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (theme == ThemeManager.Dark || theme == ThemeManager.Black || theme == ThemeManager.Nord)
|
if (theme == ThemeManager.Dark || theme == ThemeManager.Black || theme == ThemeManager.Nord || theme == ThemeManager.SolarizedDark)
|
||||||
{
|
{
|
||||||
LightTheme = false;
|
LightTheme = false;
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
src/Android/lib/arm64-v8a/libargon2.so
Executable file
BIN
src/Android/lib/arm64-v8a/libargon2.so
Executable file
Binary file not shown.
BIN
src/Android/lib/armeabi-v7a/libargon2.so
Executable file
BIN
src/Android/lib/armeabi-v7a/libargon2.so
Executable file
Binary file not shown.
BIN
src/Android/lib/x86/libargon2.so
Executable file
BIN
src/Android/lib/x86/libargon2.so
Executable file
Binary file not shown.
BIN
src/Android/lib/x86_64/libargon2.so
Executable file
BIN
src/Android/lib/x86_64/libargon2.so
Executable file
Binary file not shown.
@@ -1,5 +1,6 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models;
|
||||||
|
|
||||||
namespace Bit.App.Abstractions
|
namespace Bit.App.Abstractions
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -143,6 +143,7 @@
|
|||||||
<Folder Include="Utilities\AccountManagement\" />
|
<Folder Include="Utilities\AccountManagement\" />
|
||||||
<Folder Include="Controls\DateTime\" />
|
<Folder Include="Controls\DateTime\" />
|
||||||
<Folder Include="Controls\IconLabelButton\" />
|
<Folder Include="Controls\IconLabelButton\" />
|
||||||
|
<Folder Include="Controls\PasswordStrengthProgressBar\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -435,5 +436,6 @@
|
|||||||
<None Remove="Utilities\AccountManagement\" />
|
<None Remove="Utilities\AccountManagement\" />
|
||||||
<None Remove="Controls\DateTime\" />
|
<None Remove="Controls\DateTime\" />
|
||||||
<None Remove="Controls\IconLabelButton\" />
|
<None Remove="Controls\IconLabelButton\" />
|
||||||
|
<None Remove="Controls\PasswordStrengthProgressBar\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -459,14 +459,7 @@ namespace Bit.App
|
|||||||
switch (navTarget)
|
switch (navTarget)
|
||||||
{
|
{
|
||||||
case NavigationTarget.HomeLogin:
|
case NavigationTarget.HomeLogin:
|
||||||
if (navParams is HomeNavigationParams homeParams)
|
Current.MainPage = new NavigationPage(new HomePage(Options));
|
||||||
{
|
|
||||||
Current.MainPage = new NavigationPage(new HomePage(Options, homeParams.ShouldCheckRememberEmail));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Current.MainPage = new NavigationPage(new HomePage(Options));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case NavigationTarget.Login:
|
case NavigationTarget.Login:
|
||||||
if (navParams is LoginNavigationParams loginParams)
|
if (navParams is LoginNavigationParams loginParams)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Bit.App.Controls
|
|||||||
{
|
{
|
||||||
AccountView = accountView;
|
AccountView = accountView;
|
||||||
AvatarImageSource = ServiceContainer.Resolve<IAvatarImageSourcePool>("avatarImageSourcePool")
|
AvatarImageSource = ServiceContainer.Resolve<IAvatarImageSourcePool>("avatarImageSourcePool")
|
||||||
?.GetOrCreateAvatar(AccountView.UserId, AccountView.Name, AccountView.Email);
|
?.GetOrCreateAvatar(AccountView.UserId, AccountView.Name, AccountView.Email, AccountView.AvatarColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccountView AccountView
|
public AccountView AccountView
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace Bit.App.Controls
|
|||||||
{
|
{
|
||||||
private readonly string _text;
|
private readonly string _text;
|
||||||
private readonly string _id;
|
private readonly string _id;
|
||||||
|
private readonly string _color;
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
@@ -23,7 +24,7 @@ namespace Bit.App.Controls
|
|||||||
|
|
||||||
if (obj is AvatarImageSource avatar)
|
if (obj is AvatarImageSource avatar)
|
||||||
{
|
{
|
||||||
return avatar._id == _id && avatar._text == _text;
|
return avatar._id == _id && avatar._text == _text && avatar._color == _color;
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.Equals(obj);
|
return base.Equals(obj);
|
||||||
@@ -31,7 +32,7 @@ namespace Bit.App.Controls
|
|||||||
|
|
||||||
public override int GetHashCode() => _id?.GetHashCode() ?? _text?.GetHashCode() ?? -1;
|
public override int GetHashCode() => _id?.GetHashCode() ?? _text?.GetHashCode() ?? -1;
|
||||||
|
|
||||||
public AvatarImageSource(string userId = null, string name = null, string email = null)
|
public AvatarImageSource(string userId = null, string name = null, string email = null, string color = null)
|
||||||
{
|
{
|
||||||
_id = userId;
|
_id = userId;
|
||||||
_text = name;
|
_text = name;
|
||||||
@@ -39,6 +40,7 @@ namespace Bit.App.Controls
|
|||||||
{
|
{
|
||||||
_text = email;
|
_text = email;
|
||||||
}
|
}
|
||||||
|
_color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Func<CancellationToken, Task<Stream>> Stream => GetStreamAsync;
|
public override Func<CancellationToken, Task<Stream>> Stream => GetStreamAsync;
|
||||||
@@ -71,7 +73,7 @@ namespace Bit.App.Controls
|
|||||||
chars = upperCaseText = _text.ToUpper();
|
chars = upperCaseText = _text.ToUpper();
|
||||||
}
|
}
|
||||||
|
|
||||||
var bgColor = CoreHelpers.StringToColor(_id ?? upperCaseText, "#33ffffff");
|
var bgColor = _color ?? CoreHelpers.StringToColor(_id ?? upperCaseText, "#33ffffff");
|
||||||
var textColor = CoreHelpers.TextColorFromBgColor(bgColor);
|
var textColor = CoreHelpers.TextColorFromBgColor(bgColor);
|
||||||
var size = 50;
|
var size = 50;
|
||||||
|
|
||||||
|
|||||||
@@ -5,19 +5,19 @@ namespace Bit.App.Controls
|
|||||||
{
|
{
|
||||||
public interface IAvatarImageSourcePool
|
public interface IAvatarImageSourcePool
|
||||||
{
|
{
|
||||||
AvatarImageSource GetOrCreateAvatar(string userId, string name, string email);
|
AvatarImageSource GetOrCreateAvatar(string userId, string name, string email, string color);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AvatarImageSourcePool : IAvatarImageSourcePool
|
public class AvatarImageSourcePool : IAvatarImageSourcePool
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<string, AvatarImageSource> _cache = new ConcurrentDictionary<string, AvatarImageSource>();
|
private readonly ConcurrentDictionary<string, AvatarImageSource> _cache = new ConcurrentDictionary<string, AvatarImageSource>();
|
||||||
|
|
||||||
public AvatarImageSource GetOrCreateAvatar(string userId, string name, string email)
|
public AvatarImageSource GetOrCreateAvatar(string userId, string name, string email, string color)
|
||||||
{
|
{
|
||||||
var key = $"{userId}{name}{email}";
|
var key = $"{userId}{name}{email}{color}";
|
||||||
if (!_cache.TryGetValue(key, out var avatar))
|
if (!_cache.TryGetValue(key, out var avatar))
|
||||||
{
|
{
|
||||||
avatar = new AvatarImageSource(userId, name, email);
|
avatar = new AvatarImageSource(userId, name, email, color);
|
||||||
if (!_cache.TryAdd(key, avatar)
|
if (!_cache.TryAdd(key, avatar)
|
||||||
&&
|
&&
|
||||||
!_cache.TryGetValue(key, out avatar)) // If add fails another thread created the avatar in between the first try get and the try add.
|
!_cache.TryGetValue(key, out avatar)) // If add fails another thread created the avatar in between the first try get and the try add.
|
||||||
|
|||||||
@@ -21,13 +21,13 @@ namespace Bit.App.Controls
|
|||||||
nameof(StrokeWidth), typeof(float), typeof(CircularProgressbarView), 3f);
|
nameof(StrokeWidth), typeof(float), typeof(CircularProgressbarView), 3f);
|
||||||
|
|
||||||
public static readonly BindableProperty ProgressColorProperty = BindableProperty.Create(
|
public static readonly BindableProperty ProgressColorProperty = BindableProperty.Create(
|
||||||
nameof(ProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.Default);
|
nameof(ProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.FromHex("175DDC"));
|
||||||
|
|
||||||
public static readonly BindableProperty EndingProgressColorProperty = BindableProperty.Create(
|
public static readonly BindableProperty EndingProgressColorProperty = BindableProperty.Create(
|
||||||
nameof(EndingProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.Default);
|
nameof(EndingProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.FromHex("dd4b39"));
|
||||||
|
|
||||||
public static readonly BindableProperty BackgroundProgressColorProperty = BindableProperty.Create(
|
public static readonly BindableProperty BackgroundProgressColorProperty = BindableProperty.Create(
|
||||||
nameof(BackgroundProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.Default);
|
nameof(BackgroundProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.White);
|
||||||
|
|
||||||
public double Progress
|
public double Progress
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using Xamarin.Forms;
|
using System.Linq;
|
||||||
|
using Xamarin.CommunityToolkit.Converters;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Controls
|
namespace Bit.App.Controls
|
||||||
{
|
{
|
||||||
@@ -6,4 +8,13 @@ namespace Bit.App.Controls
|
|||||||
{
|
{
|
||||||
public string ExtraDataForLogging { get; set; }
|
public string ExtraDataForLogging { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class SelectionChangedEventArgsConverter : BaseNullableConverterOneWay<SelectionChangedEventArgs, object>
|
||||||
|
{
|
||||||
|
public override object? ConvertFrom(SelectionChangedEventArgs? value)
|
||||||
|
{
|
||||||
|
return value?.CurrentSelection.FirstOrDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Bit.App.Controls
|
|||||||
public class ExtendedSlider : Slider
|
public class ExtendedSlider : Slider
|
||||||
{
|
{
|
||||||
public static readonly BindableProperty ThumbBorderColorProperty = BindableProperty.Create(
|
public static readonly BindableProperty ThumbBorderColorProperty = BindableProperty.Create(
|
||||||
nameof(ThumbBorderColor), typeof(Color), typeof(ExtendedSlider), Color.Default);
|
nameof(ThumbBorderColor), typeof(Color), typeof(ExtendedSlider), Color.FromHex("b5b5b5"));
|
||||||
|
|
||||||
public Color ThumbBorderColor
|
public Color ThumbBorderColor
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ namespace Bit.App.Controls
|
|||||||
public class ExtendedStepper : Stepper
|
public class ExtendedStepper : Stepper
|
||||||
{
|
{
|
||||||
public static readonly BindableProperty StepperBackgroundColorProperty = BindableProperty.Create(
|
public static readonly BindableProperty StepperBackgroundColorProperty = BindableProperty.Create(
|
||||||
nameof(StepperBackgroundColor), typeof(Color), typeof(ExtendedStepper), Color.Default);
|
nameof(StepperBackgroundColor), typeof(Color), typeof(ExtendedStepper), Color.White);
|
||||||
|
|
||||||
public static readonly BindableProperty StepperForegroundColorProperty = BindableProperty.Create(
|
public static readonly BindableProperty StepperForegroundColorProperty = BindableProperty.Create(
|
||||||
nameof(StepperForegroundColor), typeof(Color), typeof(ExtendedStepper), Color.Default);
|
nameof(StepperForegroundColor), typeof(Color), typeof(ExtendedStepper), Color.Black);
|
||||||
|
|
||||||
public Color StepperBackgroundColor
|
public Color StepperBackgroundColor
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Bit.App.Controls
|
||||||
|
{
|
||||||
|
public interface IPasswordStrengthable
|
||||||
|
{
|
||||||
|
string Password { get; }
|
||||||
|
List<string> UserInputs { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using Bit.Core.Attributes;
|
||||||
|
|
||||||
|
namespace Bit.App.Controls
|
||||||
|
{
|
||||||
|
public enum PasswordStrengthLevel
|
||||||
|
{
|
||||||
|
[LocalizableEnum("Weak")]
|
||||||
|
VeryWeak,
|
||||||
|
[LocalizableEnum("Weak")]
|
||||||
|
Weak,
|
||||||
|
[LocalizableEnum("Good")]
|
||||||
|
Good,
|
||||||
|
[LocalizableEnum("Strong")]
|
||||||
|
Strong
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<StackLayout
|
||||||
|
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||||
|
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||||
|
x:DataType="controls:PasswordStrengthViewModel"
|
||||||
|
x:Class="Bit.App.Controls.PasswordStrengthProgressBar"
|
||||||
|
StyleClass="box">
|
||||||
|
|
||||||
|
<StackLayout.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<u:LocalizableEnumConverter x:Key="localizableEnum" />
|
||||||
|
</ResourceDictionary>
|
||||||
|
</StackLayout.Resources>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
x:Name="_progressBar"
|
||||||
|
u:ProgressBarExtensions.AnimatedProgress="{Binding PasswordStrength}"
|
||||||
|
ScaleY="2" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
x:Name="_progressLabel"
|
||||||
|
Text="{Binding PasswordStrengthLevel, Converter={StaticResource localizableEnum}, TargetNullValue=' ' }"
|
||||||
|
StyleClass="box-footer-label" />
|
||||||
|
|
||||||
|
</StackLayout>
|
||||||
|
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
using System;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Bit.App.Controls
|
||||||
|
{
|
||||||
|
public partial class PasswordStrengthProgressBar : StackLayout
|
||||||
|
{
|
||||||
|
public static readonly BindableProperty PasswordStrengthLevelProperty = BindableProperty.Create(
|
||||||
|
nameof(PasswordStrengthLevel),
|
||||||
|
typeof(PasswordStrengthLevel),
|
||||||
|
typeof(PasswordStrengthProgressBar),
|
||||||
|
propertyChanged: OnControlPropertyChanged);
|
||||||
|
|
||||||
|
public static readonly BindableProperty VeryWeakColorProperty = BindableProperty.Create(
|
||||||
|
nameof(VeryWeakColor),
|
||||||
|
typeof(Color),
|
||||||
|
typeof(PasswordStrengthProgressBar),
|
||||||
|
propertyChanged: OnControlPropertyChanged);
|
||||||
|
|
||||||
|
public static readonly BindableProperty WeakColorProperty = BindableProperty.Create(
|
||||||
|
nameof(WeakColor),
|
||||||
|
typeof(Color),
|
||||||
|
typeof(PasswordStrengthProgressBar),
|
||||||
|
propertyChanged: OnControlPropertyChanged);
|
||||||
|
|
||||||
|
public static readonly BindableProperty GoodColorProperty = BindableProperty.Create(
|
||||||
|
nameof(GoodColor),
|
||||||
|
typeof(Color),
|
||||||
|
typeof(PasswordStrengthProgressBar),
|
||||||
|
propertyChanged: OnControlPropertyChanged);
|
||||||
|
|
||||||
|
public static readonly BindableProperty StrongColorProperty = BindableProperty.Create(
|
||||||
|
nameof(StrongColor),
|
||||||
|
typeof(Color),
|
||||||
|
typeof(PasswordStrengthProgressBar),
|
||||||
|
propertyChanged: OnControlPropertyChanged);
|
||||||
|
|
||||||
|
public PasswordStrengthLevel? PasswordStrengthLevel
|
||||||
|
{
|
||||||
|
get { return (PasswordStrengthLevel?)GetValue(PasswordStrengthLevelProperty); }
|
||||||
|
set { SetValue(PasswordStrengthLevelProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color VeryWeakColor
|
||||||
|
{
|
||||||
|
get { return (Color)GetValue(VeryWeakColorProperty); }
|
||||||
|
set { SetValue(VeryWeakColorProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color WeakColor
|
||||||
|
{
|
||||||
|
get { return (Color)GetValue(WeakColorProperty); }
|
||||||
|
set { SetValue(WeakColorProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color GoodColor
|
||||||
|
{
|
||||||
|
get { return (Color)GetValue(GoodColorProperty); }
|
||||||
|
set { SetValue(GoodColorProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color StrongColor
|
||||||
|
{
|
||||||
|
get { return (Color)GetValue(StrongColorProperty); }
|
||||||
|
set { SetValue(StrongColorProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public PasswordStrengthProgressBar()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
SetBinding(PasswordStrengthProgressBar.PasswordStrengthLevelProperty, new Binding() { Path = nameof(PasswordStrengthViewModel.PasswordStrengthLevel) });
|
||||||
|
UpdateColors();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnControlPropertyChanged(BindableObject bindable, object oldValue, object newValue)
|
||||||
|
{
|
||||||
|
(bindable as PasswordStrengthProgressBar)?.UpdateColors();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateColors()
|
||||||
|
{
|
||||||
|
if (_progressBar == null || _progressLabel == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_progressBar.ProgressColor = GetColorForStrength();
|
||||||
|
_progressLabel.TextColor = _progressBar.ProgressColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color GetColorForStrength()
|
||||||
|
{
|
||||||
|
switch (PasswordStrengthLevel)
|
||||||
|
{
|
||||||
|
case Controls.PasswordStrengthLevel.VeryWeak:
|
||||||
|
return VeryWeakColor;
|
||||||
|
case Controls.PasswordStrengthLevel.Weak:
|
||||||
|
return WeakColor;
|
||||||
|
case Controls.PasswordStrengthLevel.Good:
|
||||||
|
return GoodColor;
|
||||||
|
case Controls.PasswordStrengthLevel.Strong:
|
||||||
|
return StrongColor;
|
||||||
|
default:
|
||||||
|
return Color.Transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Bit.App.Controls
|
||||||
|
{
|
||||||
|
public class PasswordStrengthViewModel : ExtendedViewModel
|
||||||
|
{
|
||||||
|
private readonly IPasswordGenerationService _passwordGenerationService;
|
||||||
|
private readonly IPasswordStrengthable _passwordStrengthable;
|
||||||
|
private double _passwordStrength;
|
||||||
|
private Color _passwordColor;
|
||||||
|
private PasswordStrengthLevel? _passwordStrengthLevel;
|
||||||
|
|
||||||
|
public PasswordStrengthViewModel(IPasswordStrengthable passwordStrengthable)
|
||||||
|
{
|
||||||
|
_passwordGenerationService = ServiceContainer.Resolve<IPasswordGenerationService>();
|
||||||
|
_passwordStrengthable = passwordStrengthable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double PasswordStrength
|
||||||
|
{
|
||||||
|
get => _passwordStrength;
|
||||||
|
set => SetProperty(ref _passwordStrength, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PasswordStrengthLevel? PasswordStrengthLevel
|
||||||
|
{
|
||||||
|
get => _passwordStrengthLevel;
|
||||||
|
set => SetProperty(ref _passwordStrengthLevel, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> GetPasswordStrengthUserInput(string email) => _passwordGenerationService.GetPasswordStrengthUserInput(email);
|
||||||
|
|
||||||
|
public void CalculatePasswordStrength()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_passwordStrengthable.Password))
|
||||||
|
{
|
||||||
|
PasswordStrength = 0;
|
||||||
|
PasswordStrengthLevel = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var passwordStrength = _passwordGenerationService.PasswordStrength(_passwordStrengthable.Password, _passwordStrengthable.UserInputs);
|
||||||
|
// The passwordStrength.Score is 0..4, convertion was made to be used as a progress directly by the control 0..1
|
||||||
|
PasswordStrength = (passwordStrength.Score + 1f) / 5f;
|
||||||
|
if (PasswordStrength <= 0.4f)
|
||||||
|
{
|
||||||
|
PasswordStrengthLevel = Controls.PasswordStrengthLevel.VeryWeak;
|
||||||
|
}
|
||||||
|
else if (PasswordStrength <= 0.6f)
|
||||||
|
{
|
||||||
|
PasswordStrengthLevel = Controls.PasswordStrengthLevel.Weak;
|
||||||
|
}
|
||||||
|
else if (PasswordStrength <= 0.8f)
|
||||||
|
{
|
||||||
|
PasswordStrengthLevel = Controls.PasswordStrengthLevel.Good;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PasswordStrengthLevel = Controls.PasswordStrengthLevel.Strong;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -4,6 +4,8 @@ using System.Text.RegularExpressions;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
|
using Bit.App.Utilities;
|
||||||
|
using Bit.Core;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Models.Domain;
|
using Bit.Core.Models.Domain;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
@@ -147,8 +149,8 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
if (IsPolicyInEffect)
|
if (IsPolicyInEffect)
|
||||||
{
|
{
|
||||||
var userInput = await GetPasswordStrengthUserInput();
|
var userInputs = _passwordGenerationService.GetPasswordStrengthUserInput(await _stateService.GetEmailAsync());
|
||||||
var passwordStrength = _passwordGenerationService.PasswordStrength(MasterPassword, userInput);
|
var passwordStrength = _passwordGenerationService.PasswordStrength(MasterPassword, userInputs);
|
||||||
if (!await _policyService.EvaluateMasterPassword(passwordStrength.Score, MasterPassword, Policy))
|
if (!await _policyService.EvaluateMasterPassword(passwordStrength.Score, MasterPassword, Policy))
|
||||||
{
|
{
|
||||||
await _platformUtilsService.ShowDialogAsync(AppResources.MasterPasswordPolicyValidationMessage,
|
await _platformUtilsService.ShowDialogAsync(AppResources.MasterPasswordPolicyValidationMessage,
|
||||||
@@ -158,7 +160,7 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (MasterPassword.Length < 8)
|
if (MasterPassword.Length < Constants.MasterPasswordMinimumChars)
|
||||||
{
|
{
|
||||||
await _platformUtilsService.ShowDialogAsync(AppResources.MasterPasswordLengthValMessage,
|
await _platformUtilsService.ShowDialogAsync(AppResources.MasterPasswordLengthValMessage,
|
||||||
AppResources.MasterPasswordPolicyValidationTitle, AppResources.Ok);
|
AppResources.MasterPasswordPolicyValidationTitle, AppResources.Ok);
|
||||||
@@ -174,19 +176,5 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<List<string>> GetPasswordStrengthUserInput()
|
|
||||||
{
|
|
||||||
var email = await _stateService.GetEmailAsync();
|
|
||||||
List<string> userInput = null;
|
|
||||||
var atPosition = email.IndexOf('@');
|
|
||||||
if (atPosition > -1)
|
|
||||||
{
|
|
||||||
var rx = new Regex("/[^A-Za-z0-9]/", RegexOptions.Compiled);
|
|
||||||
var data = rx.Split(email.Substring(0, atPosition).Trim().ToLower());
|
|
||||||
userInput = new List<string>(data);
|
|
||||||
}
|
|
||||||
return userInput;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,9 @@
|
|||||||
x:Name="_email"
|
x:Name="_email"
|
||||||
Text="{Binding Email}"
|
Text="{Binding Email}"
|
||||||
Keyboard="Email"
|
Keyboard="Email"
|
||||||
StyleClass="box-value">
|
StyleClass="box-value"
|
||||||
|
ReturnType="Go"
|
||||||
|
ReturnCommand="{Binding ContinueCommand}">
|
||||||
<VisualStateManager.VisualStateGroups>
|
<VisualStateManager.VisualStateGroups>
|
||||||
<VisualStateGroup x:Name="CommonStates">
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
<VisualState x:Name="Disabled">
|
<VisualState x:Name="Disabled">
|
||||||
|
|||||||
@@ -15,14 +15,13 @@ namespace Bit.App.Pages
|
|||||||
private readonly AppOptions _appOptions;
|
private readonly AppOptions _appOptions;
|
||||||
private IBroadcasterService _broadcasterService;
|
private IBroadcasterService _broadcasterService;
|
||||||
|
|
||||||
public HomePage(AppOptions appOptions = null, bool shouldCheckRememberEmail = true)
|
public HomePage(AppOptions appOptions = null)
|
||||||
{
|
{
|
||||||
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
|
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
|
||||||
_appOptions = appOptions;
|
_appOptions = appOptions;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_vm = BindingContext as HomeViewModel;
|
_vm = BindingContext as HomeViewModel;
|
||||||
_vm.Page = this;
|
_vm.Page = this;
|
||||||
_vm.ShouldCheckRememberEmail = shouldCheckRememberEmail;
|
|
||||||
_vm.ShowCancelButton = _appOptions?.IosExtension ?? false;
|
_vm.ShowCancelButton = _appOptions?.IosExtension ?? false;
|
||||||
_vm.StartLoginAction = async () => await StartLoginAsync();
|
_vm.StartLoginAction = async () => await StartLoginAsync();
|
||||||
_vm.StartRegisterAction = () => Device.BeginInvokeOnMainThread(async () => await StartRegisterAsync());
|
_vm.StartRegisterAction = () => Device.BeginInvokeOnMainThread(async () => await StartRegisterAsync());
|
||||||
@@ -71,8 +70,6 @@ namespace Bit.App.Pages
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm.CheckNavigateLoginStep();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnBackButtonPressed()
|
protected override bool OnBackButtonPressed()
|
||||||
|
|||||||
@@ -73,8 +73,6 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
public bool CanContinue => !string.IsNullOrEmpty(Email);
|
public bool CanContinue => !string.IsNullOrEmpty(Email);
|
||||||
|
|
||||||
public bool ShouldCheckRememberEmail { get; set; }
|
|
||||||
|
|
||||||
public FormattedString CreateAccountText
|
public FormattedString CreateAccountText
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -110,15 +108,6 @@ namespace Bit.App.Pages
|
|||||||
RememberEmail = !string.IsNullOrEmpty(Email);
|
RememberEmail = !string.IsNullOrEmpty(Email);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CheckNavigateLoginStep()
|
|
||||||
{
|
|
||||||
if (ShouldCheckRememberEmail && RememberEmail)
|
|
||||||
{
|
|
||||||
StartLoginAction();
|
|
||||||
}
|
|
||||||
ShouldCheckRememberEmail = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ContinueToLoginStepAsync()
|
public async Task ContinueToLoginStepAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -136,16 +125,16 @@ namespace Bit.App.Pages
|
|||||||
AppResources.Ok);
|
AppResources.Ok);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _stateService.SetRememberedEmailAsync(RememberEmail ? Email : null);
|
await _stateService.SetRememberedEmailAsync(RememberEmail ? Email : null);
|
||||||
var userId = await _stateService.GetUserIdAsync(Email);
|
var userId = await _stateService.GetUserIdAsync(Email);
|
||||||
if (!string.IsNullOrWhiteSpace(userId))
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(userId) &&
|
||||||
|
(await _stateService.GetEnvironmentUrlsAsync(userId))?.Base == _environmentService.BaseUrl &&
|
||||||
|
await _stateService.IsAuthenticatedAsync(userId))
|
||||||
{
|
{
|
||||||
var userEnvUrls = await _stateService.GetEnvironmentUrlsAsync(userId);
|
await _accountManager.PromptToSwitchToExistingAccountAsync(userId);
|
||||||
if (userEnvUrls?.Base == _environmentService.BaseUrl)
|
return;
|
||||||
{
|
|
||||||
await _accountManager.PromptToSwitchToExistingAccountAsync(userId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
StartLoginAction();
|
StartLoginAction();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ namespace Bit.App.Pages
|
|||||||
private readonly IBiometricService _biometricService;
|
private readonly IBiometricService _biometricService;
|
||||||
private readonly IKeyConnectorService _keyConnectorService;
|
private readonly IKeyConnectorService _keyConnectorService;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
private readonly IWatchDeviceService _watchDeviceService;
|
||||||
private readonly WeakEventManager<int?> _secretEntryFocusWeakEventManager = new WeakEventManager<int?>();
|
private readonly WeakEventManager<int?> _secretEntryFocusWeakEventManager = new WeakEventManager<int?>();
|
||||||
|
|
||||||
private string _email;
|
private string _email;
|
||||||
@@ -56,6 +57,7 @@ namespace Bit.App.Pages
|
|||||||
_biometricService = ServiceContainer.Resolve<IBiometricService>("biometricService");
|
_biometricService = ServiceContainer.Resolve<IBiometricService>("biometricService");
|
||||||
_keyConnectorService = ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService");
|
_keyConnectorService = ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService");
|
||||||
_logger = ServiceContainer.Resolve<ILogger>("logger");
|
_logger = ServiceContainer.Resolve<ILogger>("logger");
|
||||||
|
_watchDeviceService = ServiceContainer.Resolve<IWatchDeviceService>();
|
||||||
|
|
||||||
PageTitle = AppResources.VerifyMasterPassword;
|
PageTitle = AppResources.VerifyMasterPassword;
|
||||||
TogglePasswordCommand = new Command(TogglePassword);
|
TogglePasswordCommand = new Command(TogglePassword);
|
||||||
@@ -226,8 +228,7 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
|
|
||||||
ShowPassword = false;
|
ShowPassword = false;
|
||||||
var kdf = await _stateService.GetKdfTypeAsync();
|
var kdfConfig = await _stateService.GetActiveUserCustomDataAsync(a => new KdfConfig(a?.Profile));
|
||||||
var kdfIterations = await _stateService.GetKdfIterationsAsync();
|
|
||||||
|
|
||||||
if (PinLock)
|
if (PinLock)
|
||||||
{
|
{
|
||||||
@@ -237,7 +238,7 @@ namespace Bit.App.Pages
|
|||||||
if (_isPinProtected)
|
if (_isPinProtected)
|
||||||
{
|
{
|
||||||
var key = await _cryptoService.MakeKeyFromPinAsync(Pin, _email,
|
var key = await _cryptoService.MakeKeyFromPinAsync(Pin, _email,
|
||||||
kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000),
|
kdfConfig,
|
||||||
await _stateService.GetPinProtectedKeyAsync());
|
await _stateService.GetPinProtectedKeyAsync());
|
||||||
var encKey = await _cryptoService.GetEncKeyAsync(key);
|
var encKey = await _cryptoService.GetEncKeyAsync(key);
|
||||||
var protectedPin = await _stateService.GetProtectedPinAsync();
|
var protectedPin = await _stateService.GetProtectedPinAsync();
|
||||||
@@ -252,8 +253,7 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var key = await _cryptoService.MakeKeyFromPinAsync(Pin, _email,
|
var key = await _cryptoService.MakeKeyFromPinAsync(Pin, _email, kdfConfig);
|
||||||
kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000));
|
|
||||||
failed = false;
|
failed = false;
|
||||||
Pin = string.Empty;
|
Pin = string.Empty;
|
||||||
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
|
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
|
||||||
@@ -278,7 +278,7 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var key = await _cryptoService.MakeKeyAsync(MasterPassword, _email, kdf, kdfIterations);
|
var key = await _cryptoService.MakeKeyAsync(MasterPassword, _email, kdfConfig);
|
||||||
var storedKeyHash = await _cryptoService.GetKeyHashAsync();
|
var storedKeyHash = await _cryptoService.GetKeyHashAsync();
|
||||||
var passwordValid = false;
|
var passwordValid = false;
|
||||||
|
|
||||||
@@ -312,8 +312,7 @@ namespace Bit.App.Pages
|
|||||||
var protectedPin = await _stateService.GetProtectedPinAsync();
|
var protectedPin = await _stateService.GetProtectedPinAsync();
|
||||||
var encKey = await _cryptoService.GetEncKeyAsync(key);
|
var encKey = await _cryptoService.GetEncKeyAsync(key);
|
||||||
var decPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), encKey);
|
var decPin = await _cryptoService.DecryptToUtf8Async(new EncString(protectedPin), encKey);
|
||||||
var pinKey = await _cryptoService.MakePinKeyAysnc(decPin, _email,
|
var pinKey = await _cryptoService.MakePinKeyAysnc(decPin, _email, kdfConfig);
|
||||||
kdf.GetValueOrDefault(KdfType.PBKDF2_SHA256), kdfIterations.GetValueOrDefault(5000));
|
|
||||||
await _stateService.SetPinProtectedKeyAsync(await _cryptoService.EncryptAsync(key.Key, pinKey));
|
await _stateService.SetPinProtectedKeyAsync(await _cryptoService.EncryptAsync(key.Key, pinKey));
|
||||||
}
|
}
|
||||||
MasterPassword = string.Empty;
|
MasterPassword = string.Empty;
|
||||||
@@ -387,6 +386,7 @@ namespace Bit.App.Pages
|
|||||||
private async Task DoContinueAsync()
|
private async Task DoContinueAsync()
|
||||||
{
|
{
|
||||||
await _stateService.SetBiometricLockedAsync(false);
|
await _stateService.SetBiometricLockedAsync(false);
|
||||||
|
_watchDeviceService.SyncDataToWatchAsync().FireAndForget();
|
||||||
_messagingService.Send("unlocked");
|
_messagingService.Send("unlocked");
|
||||||
UnlockedAction?.Invoke();
|
UnlockedAction?.Invoke();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -305,15 +305,5 @@ namespace Bit.App.Pages
|
|||||||
_logger.Exception(e);
|
_logger.Exception(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleException(Exception ex)
|
|
||||||
{
|
|
||||||
Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
|
|
||||||
{
|
|
||||||
await _deviceActionService.HideLoadingAsync();
|
|
||||||
await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage);
|
|
||||||
}).FireAndForget();
|
|
||||||
_logger.Exception(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
|
|
||||||
var loginRequestData = await _authService.GetPasswordlessLoginRequestByIdAsync(LoginRequest.Id);
|
var loginRequestData = await _authService.GetPasswordlessLoginRequestByIdAsync(LoginRequest.Id);
|
||||||
if (loginRequestData.RequestApproved.HasValue && loginRequestData.ResponseDate.HasValue)
|
if (loginRequestData.IsAnswered)
|
||||||
{
|
{
|
||||||
await _platformUtilsService.ShowDialogAsync(AppResources.ThisRequestIsNoLongerValid);
|
await _platformUtilsService.ShowDialogAsync(AppResources.ThisRequestIsNoLongerValid);
|
||||||
await Page.Navigation.PopModalAsync();
|
await Page.Navigation.PopModalAsync();
|
||||||
@@ -148,16 +148,6 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
return string.Format(AppResources.XMinutesAgo, DateTime.UtcNow.Minute - requestDate.Value.ToUniversalTime().Minute);
|
return string.Format(AppResources.XMinutesAgo, DateTime.UtcNow.Minute - requestDate.Value.ToUniversalTime().Minute);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleException(Exception ex)
|
|
||||||
{
|
|
||||||
Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
|
|
||||||
{
|
|
||||||
await _deviceActionService.HideLoadingAsync();
|
|
||||||
await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage);
|
|
||||||
}).FireAndForget();
|
|
||||||
_logger.Exception(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LoginPasswordlessDetails
|
public class LoginPasswordlessDetails
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
</ContentPage.ToolbarItems>
|
</ContentPage.ToolbarItems>
|
||||||
|
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<StackLayout Spacing="20">
|
<StackLayout Spacing="10">
|
||||||
<StackLayout StyleClass="box">
|
<StackLayout StyleClass="box">
|
||||||
<StackLayout StyleClass="box-row">
|
<StackLayout StyleClass="box-row">
|
||||||
<Label
|
<Label
|
||||||
@@ -72,8 +72,19 @@
|
|||||||
AutomationProperties.HelpText="{Binding PasswordVisibilityAccessibilityText}"/>
|
AutomationProperties.HelpText="{Binding PasswordVisibilityAccessibilityText}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Label
|
<Label
|
||||||
Text="{u:I18n MasterPasswordDescription}"
|
StyleClass="box-sub-label"
|
||||||
StyleClass="box-footer-label" />
|
Margin="0,0,0,10">
|
||||||
|
<Label.FormattedText>
|
||||||
|
<FormattedString>
|
||||||
|
<Span Text="{u:I18n Important}" TextColor="{DynamicResource InfoColor}"/>
|
||||||
|
<Span Text=": " TextColor="{DynamicResource InfoColor}"/>
|
||||||
|
<Span Text="{Binding MasterPasswordMininumCharactersDescription}" TextColor="{DynamicResource MutedColor}"/>
|
||||||
|
</FormattedString>
|
||||||
|
</Label.FormattedText>
|
||||||
|
</Label>
|
||||||
|
<controls:PasswordStrengthProgressBar
|
||||||
|
BindingContext="{Binding PasswordStrengthViewModel}"
|
||||||
|
Margin="0,0"/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout StyleClass="box">
|
<StackLayout StyleClass="box">
|
||||||
<Grid StyleClass="box-row">
|
<Grid StyleClass="box-row">
|
||||||
@@ -126,6 +137,17 @@
|
|||||||
StyleClass="box-footer-label" />
|
StyleClass="box-footer-label" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout StyleClass="box">
|
<StackLayout StyleClass="box">
|
||||||
|
<StackLayout StyleClass="box-row, box-row-switch">
|
||||||
|
<Switch
|
||||||
|
IsToggled="{Binding CheckExposedMasterPassword}"
|
||||||
|
StyleClass="box-value"
|
||||||
|
HorizontalOptions="Start"
|
||||||
|
Margin="0, 0, 10, 0"/>
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n CheckKnownDataBreachesForThisPassword}"
|
||||||
|
StyleClass="box-footer-label"
|
||||||
|
VerticalOptions="Center"/>
|
||||||
|
</StackLayout>
|
||||||
<StackLayout StyleClass="box-row, box-row-switch"
|
<StackLayout StyleClass="box-row, box-row-switch"
|
||||||
IsVisible="{Binding ShowTerms}">
|
IsVisible="{Binding ShowTerms}">
|
||||||
<Switch
|
<Switch
|
||||||
|
|||||||
@@ -1,28 +1,36 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
|
using Bit.App.Controls;
|
||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
|
using Bit.App.Utilities;
|
||||||
using Bit.Core;
|
using Bit.Core;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.Models.Request;
|
using Bit.Core.Models.Request;
|
||||||
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
public class RegisterPageViewModel : CaptchaProtectedViewModel
|
public class RegisterPageViewModel : CaptchaProtectedViewModel, IPasswordStrengthable
|
||||||
{
|
{
|
||||||
private readonly IDeviceActionService _deviceActionService;
|
private readonly IDeviceActionService _deviceActionService;
|
||||||
private readonly II18nService _i18nService;
|
private readonly II18nService _i18nService;
|
||||||
private readonly IEnvironmentService _environmentService;
|
private readonly IEnvironmentService _environmentService;
|
||||||
|
private readonly IAuditService _auditService;
|
||||||
private readonly IApiService _apiService;
|
private readonly IApiService _apiService;
|
||||||
private readonly ICryptoService _cryptoService;
|
private readonly ICryptoService _cryptoService;
|
||||||
private readonly IPlatformUtilsService _platformUtilsService;
|
private readonly IPlatformUtilsService _platformUtilsService;
|
||||||
|
private string _email;
|
||||||
|
private string _masterPassword;
|
||||||
private bool _showPassword;
|
private bool _showPassword;
|
||||||
private bool _acceptPolicies;
|
private bool _acceptPolicies;
|
||||||
|
private bool _checkExposedMasterPassword;
|
||||||
|
|
||||||
public RegisterPageViewModel()
|
public RegisterPageViewModel()
|
||||||
{
|
{
|
||||||
@@ -32,12 +40,15 @@ namespace Bit.App.Pages
|
|||||||
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
||||||
_i18nService = ServiceContainer.Resolve<II18nService>("i18nService");
|
_i18nService = ServiceContainer.Resolve<II18nService>("i18nService");
|
||||||
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
||||||
|
_auditService = ServiceContainer.Resolve<IAuditService>();
|
||||||
|
|
||||||
PageTitle = AppResources.CreateAccount;
|
PageTitle = AppResources.CreateAccount;
|
||||||
TogglePasswordCommand = new Command(TogglePassword);
|
TogglePasswordCommand = new Command(TogglePassword);
|
||||||
ToggleConfirmPasswordCommand = new Command(ToggleConfirmPassword);
|
ToggleConfirmPasswordCommand = new Command(ToggleConfirmPassword);
|
||||||
SubmitCommand = new Command(async () => await SubmitAsync());
|
SubmitCommand = new Command(async () => await SubmitAsync());
|
||||||
ShowTerms = !_platformUtilsService.IsSelfHost();
|
ShowTerms = !_platformUtilsService.IsSelfHost();
|
||||||
|
PasswordStrengthViewModel = new PasswordStrengthViewModel(this);
|
||||||
|
CheckExposedMasterPassword = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICommand PoliciesClickCommand => new Command<string>((url) =>
|
public ICommand PoliciesClickCommand => new Command<string>((url) =>
|
||||||
@@ -61,6 +72,34 @@ namespace Bit.App.Pages
|
|||||||
get => _acceptPolicies;
|
get => _acceptPolicies;
|
||||||
set => SetProperty(ref _acceptPolicies, value);
|
set => SetProperty(ref _acceptPolicies, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool CheckExposedMasterPassword
|
||||||
|
{
|
||||||
|
get => _checkExposedMasterPassword;
|
||||||
|
set => SetProperty(ref _checkExposedMasterPassword, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string MasterPassword
|
||||||
|
{
|
||||||
|
get => _masterPassword;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetProperty(ref _masterPassword, value);
|
||||||
|
PasswordStrengthViewModel.CalculatePasswordStrength();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Email
|
||||||
|
{
|
||||||
|
get => _email;
|
||||||
|
set => SetProperty(ref _email, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Password => MasterPassword;
|
||||||
|
public List<string> UserInputs => PasswordStrengthViewModel.GetPasswordStrengthUserInput(Email);
|
||||||
|
public string MasterPasswordMininumCharactersDescription => string.Format(AppResources.YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum,
|
||||||
|
Constants.MasterPasswordMinimumChars);
|
||||||
|
public PasswordStrengthViewModel PasswordStrengthViewModel { get; }
|
||||||
public bool ShowTerms { get; set; }
|
public bool ShowTerms { get; set; }
|
||||||
public Command SubmitCommand { get; }
|
public Command SubmitCommand { get; }
|
||||||
public Command TogglePasswordCommand { get; }
|
public Command TogglePasswordCommand { get; }
|
||||||
@@ -68,13 +107,10 @@ namespace Bit.App.Pages
|
|||||||
public string ShowPasswordIcon => ShowPassword ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
|
public string ShowPasswordIcon => ShowPassword ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
|
||||||
public string PasswordVisibilityAccessibilityText => ShowPassword ? AppResources.PasswordIsVisibleTapToHide : AppResources.PasswordIsNotVisibleTapToShow;
|
public string PasswordVisibilityAccessibilityText => ShowPassword ? AppResources.PasswordIsVisibleTapToHide : AppResources.PasswordIsNotVisibleTapToShow;
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string Email { get; set; }
|
|
||||||
public string MasterPassword { get; set; }
|
|
||||||
public string ConfirmMasterPassword { get; set; }
|
public string ConfirmMasterPassword { get; set; }
|
||||||
public string Hint { get; set; }
|
public string Hint { get; set; }
|
||||||
public Action RegistrationSuccess { get; set; }
|
public Action RegistrationSuccess { get; set; }
|
||||||
public Action CloseAction { get; set; }
|
public Action CloseAction { get; set; }
|
||||||
|
|
||||||
protected override II18nService i18nService => _i18nService;
|
protected override II18nService i18nService => _i18nService;
|
||||||
protected override IEnvironmentService environmentService => _environmentService;
|
protected override IEnvironmentService environmentService => _environmentService;
|
||||||
protected override IDeviceActionService deviceActionService => _deviceActionService;
|
protected override IDeviceActionService deviceActionService => _deviceActionService;
|
||||||
@@ -110,7 +146,7 @@ namespace Bit.App.Pages
|
|||||||
AppResources.Ok);
|
AppResources.Ok);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (MasterPassword.Length < 8)
|
if (MasterPassword.Length < Constants.MasterPasswordMinimumChars)
|
||||||
{
|
{
|
||||||
await _platformUtilsService.ShowDialogAsync(AppResources.MasterPasswordLengthValMessage,
|
await _platformUtilsService.ShowDialogAsync(AppResources.MasterPasswordLengthValMessage,
|
||||||
AppResources.AnErrorHasOccurred, AppResources.Ok);
|
AppResources.AnErrorHasOccurred, AppResources.Ok);
|
||||||
@@ -128,8 +164,10 @@ namespace Bit.App.Pages
|
|||||||
AppResources.AnErrorHasOccurred, AppResources.Ok);
|
AppResources.AnErrorHasOccurred, AppResources.Ok);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (await IsPasswordWeakOrExposed())
|
||||||
// TODO: Password strength check?
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (showLoading)
|
if (showLoading)
|
||||||
{
|
{
|
||||||
@@ -138,9 +176,8 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
Name = string.IsNullOrWhiteSpace(Name) ? null : Name;
|
Name = string.IsNullOrWhiteSpace(Name) ? null : Name;
|
||||||
Email = Email.Trim().ToLower();
|
Email = Email.Trim().ToLower();
|
||||||
var kdf = KdfType.PBKDF2_SHA256;
|
var kdfConfig = new KdfConfig(KdfType.PBKDF2_SHA256, Constants.Pbkdf2Iterations, null, null);
|
||||||
var kdfIterations = 100_000;
|
var key = await _cryptoService.MakeKeyAsync(MasterPassword, Email, kdfConfig);
|
||||||
var key = await _cryptoService.MakeKeyAsync(MasterPassword, Email, kdf, kdfIterations);
|
|
||||||
var encKey = await _cryptoService.MakeEncKeyAsync(key);
|
var encKey = await _cryptoService.MakeEncKeyAsync(key);
|
||||||
var hashedPassword = await _cryptoService.HashPasswordAsync(MasterPassword, key);
|
var hashedPassword = await _cryptoService.HashPasswordAsync(MasterPassword, key);
|
||||||
var keys = await _cryptoService.MakeKeyPairAsync(encKey.Item1);
|
var keys = await _cryptoService.MakeKeyPairAsync(encKey.Item1);
|
||||||
@@ -151,8 +188,10 @@ namespace Bit.App.Pages
|
|||||||
MasterPasswordHash = hashedPassword,
|
MasterPasswordHash = hashedPassword,
|
||||||
MasterPasswordHint = Hint,
|
MasterPasswordHint = Hint,
|
||||||
Key = encKey.Item2.EncryptedString,
|
Key = encKey.Item2.EncryptedString,
|
||||||
Kdf = kdf,
|
Kdf = kdfConfig.Type,
|
||||||
KdfIterations = kdfIterations,
|
KdfIterations = kdfConfig.Iterations,
|
||||||
|
KdfMemory = kdfConfig.Memory,
|
||||||
|
KdfParallelism = kdfConfig.Parallelism,
|
||||||
Keys = new KeysRequest
|
Keys = new KeysRequest
|
||||||
{
|
{
|
||||||
PublicKey = keys.Item1,
|
PublicKey = keys.Item1,
|
||||||
@@ -160,6 +199,7 @@ namespace Bit.App.Pages
|
|||||||
},
|
},
|
||||||
CaptchaResponse = _captchaToken,
|
CaptchaResponse = _captchaToken,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: org invite?
|
// TODO: org invite?
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -208,5 +248,43 @@ namespace Bit.App.Pages
|
|||||||
entry.Focus();
|
entry.Focus();
|
||||||
entry.CursorPosition = String.IsNullOrEmpty(ConfirmMasterPassword) ? 0 : ConfirmMasterPassword.Length;
|
entry.CursorPosition = String.IsNullOrEmpty(ConfirmMasterPassword) ? 0 : ConfirmMasterPassword.Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<bool> IsPasswordWeakOrExposed()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var title = string.Empty;
|
||||||
|
var message = string.Empty;
|
||||||
|
var exposedPassword = CheckExposedMasterPassword ? await _auditService.PasswordLeakedAsync(MasterPassword) > 0 : false;
|
||||||
|
var weakPassword = PasswordStrengthViewModel.PasswordStrengthLevel <= PasswordStrengthLevel.Weak;
|
||||||
|
|
||||||
|
if (exposedPassword && weakPassword)
|
||||||
|
{
|
||||||
|
title = AppResources.WeakAndExposedMasterPassword;
|
||||||
|
message = AppResources.WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription;
|
||||||
|
}
|
||||||
|
else if (exposedPassword)
|
||||||
|
{
|
||||||
|
title = AppResources.ExposedMasterPassword;
|
||||||
|
message = AppResources.PasswordFoundInADataBreachAlertDescription;
|
||||||
|
}
|
||||||
|
else if (weakPassword)
|
||||||
|
{
|
||||||
|
title = AppResources.WeakMasterPassword;
|
||||||
|
message = AppResources.WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exposedPassword || weakPassword)
|
||||||
|
{
|
||||||
|
return !await _platformUtilsService.ShowDialogAsync(message, title, AppResources.Yes, AppResources.No);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
HandleException(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
Margin="0, 12, 0, 0"
|
Margin="0, 12, 0, 0"
|
||||||
HasShadow="False"
|
HasShadow="False"
|
||||||
BackgroundColor="Transparent"
|
BackgroundColor="Transparent"
|
||||||
BorderColor="Accent">
|
BorderColor="{DynamicResource PrimaryColor}">
|
||||||
<Label
|
<Label
|
||||||
Text="{u:I18n ResetPasswordAutoEnrollInviteWarning}"
|
Text="{u:I18n ResetPasswordAutoEnrollInviteWarning}"
|
||||||
StyleClass="text-muted, text-sm, text-bold"
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
Margin="0, 12, 0, 0"
|
Margin="0, 12, 0, 0"
|
||||||
HasShadow="False"
|
HasShadow="False"
|
||||||
BackgroundColor="Transparent"
|
BackgroundColor="Transparent"
|
||||||
BorderColor="Accent">
|
BorderColor="{DynamicResource PrimaryColor}">
|
||||||
<Label
|
<Label
|
||||||
Text="{Binding PolicySummary}"
|
Text="{Binding PolicySummary}"
|
||||||
StyleClass="text-muted, text-sm, text-bold"
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Text.RegularExpressions;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
|
using Bit.App.Utilities;
|
||||||
using Bit.Core;
|
using Bit.Core;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
@@ -137,8 +138,8 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
if (IsPolicyInEffect)
|
if (IsPolicyInEffect)
|
||||||
{
|
{
|
||||||
var userInput = await GetPasswordStrengthUserInput();
|
var userInputs = _passwordGenerationService.GetPasswordStrengthUserInput(await _stateService.GetEmailAsync());
|
||||||
var passwordStrength = _passwordGenerationService.PasswordStrength(MasterPassword, userInput);
|
var passwordStrength = _passwordGenerationService.PasswordStrength(MasterPassword, userInputs);
|
||||||
if (!await _policyService.EvaluateMasterPassword(passwordStrength.Score, MasterPassword, Policy))
|
if (!await _policyService.EvaluateMasterPassword(passwordStrength.Score, MasterPassword, Policy))
|
||||||
{
|
{
|
||||||
await Page.DisplayAlert(AppResources.MasterPasswordPolicyValidationTitle,
|
await Page.DisplayAlert(AppResources.MasterPasswordPolicyValidationTitle,
|
||||||
@@ -148,7 +149,7 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (MasterPassword.Length < 8)
|
if (MasterPassword.Length < Constants.MasterPasswordMinimumChars)
|
||||||
{
|
{
|
||||||
await Page.DisplayAlert(AppResources.MasterPasswordPolicyValidationTitle,
|
await Page.DisplayAlert(AppResources.MasterPasswordPolicyValidationTitle,
|
||||||
AppResources.MasterPasswordLengthValMessage, AppResources.Ok);
|
AppResources.MasterPasswordLengthValMessage, AppResources.Ok);
|
||||||
@@ -162,10 +163,9 @@ namespace Bit.App.Pages
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var kdf = KdfType.PBKDF2_SHA256;
|
var kdfConfig = new KdfConfig(KdfType.PBKDF2_SHA256, Constants.Pbkdf2Iterations, null, null);
|
||||||
var kdfIterations = 100000;
|
|
||||||
var email = await _stateService.GetEmailAsync();
|
var email = await _stateService.GetEmailAsync();
|
||||||
var key = await _cryptoService.MakeKeyAsync(MasterPassword, email, kdf, kdfIterations);
|
var key = await _cryptoService.MakeKeyAsync(MasterPassword, email, kdfConfig);
|
||||||
var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.ServerAuthorization);
|
var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.ServerAuthorization);
|
||||||
var localMasterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.LocalAuthorization);
|
var localMasterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.LocalAuthorization);
|
||||||
|
|
||||||
@@ -186,8 +186,10 @@ namespace Bit.App.Pages
|
|||||||
MasterPasswordHash = masterPasswordHash,
|
MasterPasswordHash = masterPasswordHash,
|
||||||
Key = encKey.Item2.EncryptedString,
|
Key = encKey.Item2.EncryptedString,
|
||||||
MasterPasswordHint = Hint,
|
MasterPasswordHint = Hint,
|
||||||
Kdf = kdf,
|
Kdf = kdfConfig.Type.GetValueOrDefault(KdfType.PBKDF2_SHA256),
|
||||||
KdfIterations = kdfIterations,
|
KdfIterations = kdfConfig.Iterations.GetValueOrDefault(Constants.Pbkdf2Iterations),
|
||||||
|
KdfMemory = kdfConfig.Memory,
|
||||||
|
KdfParallelism = kdfConfig.Parallelism,
|
||||||
OrgIdentifier = OrgIdentifier,
|
OrgIdentifier = OrgIdentifier,
|
||||||
Keys = new KeysRequest
|
Keys = new KeysRequest
|
||||||
{
|
{
|
||||||
@@ -201,8 +203,7 @@ namespace Bit.App.Pages
|
|||||||
await _deviceActionService.ShowLoadingAsync(AppResources.CreatingAccount);
|
await _deviceActionService.ShowLoadingAsync(AppResources.CreatingAccount);
|
||||||
// Set Password and relevant information
|
// Set Password and relevant information
|
||||||
await _apiService.SetPasswordAsync(request);
|
await _apiService.SetPasswordAsync(request);
|
||||||
await _stateService.SetKdfTypeAsync(kdf);
|
await _stateService.SetKdfConfigurationAsync(kdfConfig);
|
||||||
await _stateService.SetKdfIterationsAsync(kdfIterations);
|
|
||||||
await _cryptoService.SetKeyAsync(key);
|
await _cryptoService.SetKeyAsync(key);
|
||||||
await _cryptoService.SetKeyHashAsync(localMasterPasswordHash);
|
await _cryptoService.SetKeyHashAsync(localMasterPasswordHash);
|
||||||
await _cryptoService.SetEncKeyAsync(encKey.Item2.EncryptedString);
|
await _cryptoService.SetEncKeyAsync(encKey.Item2.EncryptedString);
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
Margin="0"
|
Margin="0"
|
||||||
HasShadow="False"
|
HasShadow="False"
|
||||||
BackgroundColor="Transparent"
|
BackgroundColor="Transparent"
|
||||||
BorderColor="Accent">
|
BorderColor="{DynamicResource PrimaryColor}">
|
||||||
<Label
|
<Label
|
||||||
Text="{u:I18n UpdateMasterPasswordWarning}"
|
Text="{u:I18n UpdateMasterPasswordWarning}"
|
||||||
StyleClass="text-muted, text-sm, text-bold"
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
Margin="0"
|
Margin="0"
|
||||||
HasShadow="False"
|
HasShadow="False"
|
||||||
BackgroundColor="Transparent"
|
BackgroundColor="Transparent"
|
||||||
BorderColor="Accent">
|
BorderColor="{DynamicResource PrimaryColor}">
|
||||||
<Label
|
<Label
|
||||||
Text="{Binding PolicySummary}"
|
Text="{Binding PolicySummary}"
|
||||||
StyleClass="text-muted, text-sm, text-bold"
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
|
|||||||
@@ -43,12 +43,11 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve details for key generation
|
// Retrieve details for key generation
|
||||||
var kdf = await _stateService.GetKdfTypeAsync();
|
var kdfConfig = await _stateService.GetActiveUserCustomDataAsync(a => new KdfConfig(a?.Profile));
|
||||||
var kdfIterations = await _stateService.GetKdfIterationsAsync();
|
|
||||||
var email = await _stateService.GetEmailAsync();
|
var email = await _stateService.GetEmailAsync();
|
||||||
|
|
||||||
// Create new key and hash new password
|
// Create new key and hash new password
|
||||||
var key = await _cryptoService.MakeKeyAsync(MasterPassword, email, kdf, kdfIterations);
|
var key = await _cryptoService.MakeKeyAsync(MasterPassword, email, kdfConfig);
|
||||||
var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key);
|
var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key);
|
||||||
|
|
||||||
// Create new encKey for the User
|
// Create new encKey for the User
|
||||||
|
|||||||
@@ -129,8 +129,8 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
if (useCurrentActiveAccount)
|
if (useCurrentActiveAccount)
|
||||||
{
|
{
|
||||||
return new AvatarImageSource(await _stateService.GetActiveUserIdAsync(),
|
var user = await _stateService.GetActiveUserCustomDataAsync(a => (a?.Profile?.UserId, a?.Profile?.Name, a?.Profile?.Email, a?.Profile?.AvatarColor));
|
||||||
await _stateService.GetNameAsync(), await _stateService.GetEmailAsync());
|
return new AvatarImageSource(user.UserId, user.Name, user.Email, user.AvatarColor);
|
||||||
}
|
}
|
||||||
return new AvatarImageSource();
|
return new AvatarImageSource();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
using Bit.App.Controls;
|
using System;
|
||||||
|
using Bit.App.Abstractions;
|
||||||
|
using Bit.App.Controls;
|
||||||
|
using Bit.App.Resources;
|
||||||
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Exceptions;
|
||||||
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
@@ -8,6 +14,9 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
private string _pageTitle = string.Empty;
|
private string _pageTitle = string.Empty;
|
||||||
private AvatarImageSource _avatar;
|
private AvatarImageSource _avatar;
|
||||||
|
private LazyResolve<IDeviceActionService> _deviceActionService = new LazyResolve<IDeviceActionService>();
|
||||||
|
private LazyResolve<IPlatformUtilsService> _platformUtilsService = new LazyResolve<IPlatformUtilsService>();
|
||||||
|
private LazyResolve<ILogger> _logger = new LazyResolve<ILogger>();
|
||||||
|
|
||||||
public string PageTitle
|
public string PageTitle
|
||||||
{
|
{
|
||||||
@@ -22,5 +31,21 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ContentPage Page { get; set; }
|
public ContentPage Page { get; set; }
|
||||||
|
|
||||||
|
protected void HandleException(Exception ex, string message = null)
|
||||||
|
{
|
||||||
|
if (ex is ApiException apiException && apiException.Error != null)
|
||||||
|
{
|
||||||
|
message = apiException.Error.GetSingleMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
|
||||||
|
{
|
||||||
|
await _deviceActionService.Value.HideLoadingAsync();
|
||||||
|
await _platformUtilsService.Value.ShowDialogAsync(message ?? AppResources.GenericErrorMessage);
|
||||||
|
}).FireAndForget();
|
||||||
|
_logger.Value.Exception(ex);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<pages:BaseContentPage
|
<pages:BaseContentPage
|
||||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<u:InverseBoolConverter x:Key="inverseBool" />
|
<u:InverseBoolConverter x:Key="inverseBool" />
|
||||||
<u:LocalizableEnumConverter x:Key="localizableEnum" />
|
<u:LocalizableEnumConverter x:Key="localizableEnum" />
|
||||||
|
<u:IconGlyphConverter x:Key="iconGlyphConverter" />
|
||||||
<xct:EnumToBoolConverter x:Key="enumToBool"/>
|
<xct:EnumToBoolConverter x:Key="enumToBool"/>
|
||||||
<ToolbarItem Text="{u:I18n Cancel}" Command="{Binding CloseCommand}" Order="Primary" Priority="-1"
|
<ToolbarItem Text="{u:I18n Cancel}" Command="{Binding CloseCommand}" Order="Primary" Priority="-1"
|
||||||
x:Name="_closeItem" x:Key="closeItem" />
|
x:Name="_closeItem" x:Key="closeItem" />
|
||||||
@@ -66,7 +67,7 @@
|
|||||||
Margin="0"
|
Margin="0"
|
||||||
HasShadow="False"
|
HasShadow="False"
|
||||||
BackgroundColor="Transparent"
|
BackgroundColor="Transparent"
|
||||||
BorderColor="Accent">
|
BorderColor="{DynamicResource PrimaryColor}">
|
||||||
<Label
|
<Label
|
||||||
Text="{u:I18n PasswordGeneratorPolicyInEffect}"
|
Text="{u:I18n PasswordGeneratorPolicyInEffect}"
|
||||||
StyleClass="text-muted, text-sm, text-bold"
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
@@ -251,7 +252,7 @@
|
|||||||
Grid.Row="1"/>
|
Grid.Row="1"/>
|
||||||
<controls:IconButton
|
<controls:IconButton
|
||||||
StyleClass="box-row-button, box-row-button-platform"
|
StyleClass="box-row-button, box-row-button-platform"
|
||||||
Text="{Binding ShowAnonAddyHiddenValueIcon}"
|
Text="{Binding ShowAnonAddyApiAccessToken, Converter={StaticResource inverseBool, iconGlyphConverter}, ConverterParameter={x:Static u:BooleanGlyphType.Eye}}"
|
||||||
Command="{Binding ToggleForwardedEmailHiddenValueCommand}"
|
Command="{Binding ToggleForwardedEmailHiddenValueCommand}"
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Grid.Column="1"/>
|
Grid.Column="1"/>
|
||||||
@@ -280,7 +281,7 @@
|
|||||||
IsPassword="{Binding ShowFirefoxRelayApiAccessToken, Converter={StaticResource inverseBool}}"/>
|
IsPassword="{Binding ShowFirefoxRelayApiAccessToken, Converter={StaticResource inverseBool}}"/>
|
||||||
<controls:IconButton
|
<controls:IconButton
|
||||||
StyleClass="box-row-button, box-row-button-platform"
|
StyleClass="box-row-button, box-row-button-platform"
|
||||||
Text="{Binding ShowFirefoxRelayHiddenValueIcon}"
|
Text="{Binding ShowFirefoxRelayApiAccessToken, Converter={StaticResource inverseBool, iconGlyphConverter}, ConverterParameter={x:Static u:BooleanGlyphType.Eye}}"
|
||||||
Command="{Binding ToggleForwardedEmailHiddenValueCommand}"
|
Command="{Binding ToggleForwardedEmailHiddenValueCommand}"
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Grid.Column="1"/>
|
Grid.Column="1"/>
|
||||||
@@ -301,7 +302,49 @@
|
|||||||
IsPassword="{Binding ShowSimpleLoginApiKey, Converter={StaticResource inverseBool}}"/>
|
IsPassword="{Binding ShowSimpleLoginApiKey, Converter={StaticResource inverseBool}}"/>
|
||||||
<controls:IconButton
|
<controls:IconButton
|
||||||
StyleClass="box-row-button, box-row-button-platform"
|
StyleClass="box-row-button, box-row-button-platform"
|
||||||
Text="{Binding ShowSimpleLoginHiddenValueIcon}"
|
Text="{Binding ShowSimpleLoginApiKey, Converter={StaticResource inverseBool, iconGlyphConverter}, ConverterParameter={x:Static u:BooleanGlyphType.Eye}}"
|
||||||
|
Command="{Binding ToggleForwardedEmailHiddenValueCommand}"
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="1"/>
|
||||||
|
</Grid>
|
||||||
|
<!--DUCKDUCKGO OPTIONS-->
|
||||||
|
<Grid StyleClass="box-row, box-row-input"
|
||||||
|
IsVisible="{Binding ForwardedEmailServiceSelected, Converter={StaticResource enumToBool}, ConverterParameter={x:Static enums:ForwardedEmailServiceType.DuckDuckGo}}"
|
||||||
|
Grid.RowDefinitions="Auto,*"
|
||||||
|
Grid.ColumnDefinitions="*,Auto">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n APIKeyRequiredParenthesis}"
|
||||||
|
StyleClass="box-label"/>
|
||||||
|
<Entry
|
||||||
|
x:Name="_duckDuckGoApiAccessTokenEntry"
|
||||||
|
Text="{Binding DuckDuckGoApiKey}"
|
||||||
|
StyleClass="box-value"
|
||||||
|
Grid.Row="1"
|
||||||
|
IsPassword="{Binding ShowDuckDuckGoApiKey, Converter={StaticResource inverseBool}}"/>
|
||||||
|
<controls:IconButton
|
||||||
|
StyleClass="box-row-button, box-row-button-platform"
|
||||||
|
Text="{Binding ShowDuckDuckGoApiKey, Converter={StaticResource inverseBool, iconGlyphConverter}, ConverterParameter={x:Static u:BooleanGlyphType.Eye}}"
|
||||||
|
Command="{Binding ToggleForwardedEmailHiddenValueCommand}"
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="1"/>
|
||||||
|
</Grid>
|
||||||
|
<!--FASTMAIL OPTIONS-->
|
||||||
|
<Grid StyleClass="box-row, box-row-input"
|
||||||
|
IsVisible="{Binding ForwardedEmailServiceSelected, Converter={StaticResource enumToBool}, ConverterParameter={x:Static enums:ForwardedEmailServiceType.Fastmail}}"
|
||||||
|
Grid.RowDefinitions="Auto,*"
|
||||||
|
Grid.ColumnDefinitions="*,Auto">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n APIKeyRequiredParenthesis}"
|
||||||
|
StyleClass="box-label"/>
|
||||||
|
<Entry
|
||||||
|
x:Name="_fastmailApiAccessTokenEntry"
|
||||||
|
Text="{Binding FastmailApiKey}"
|
||||||
|
StyleClass="box-value"
|
||||||
|
Grid.Row="1"
|
||||||
|
IsPassword="{Binding ShowFastmailApiKey, Converter={StaticResource inverseBool}}"/>
|
||||||
|
<controls:IconButton
|
||||||
|
StyleClass="box-row-button, box-row-button-platform"
|
||||||
|
Text="{Binding ShowFastmailApiKey, Converter={StaticResource iconGlyphConverter}, ConverterParameter={x:Static u:BooleanGlyphType.Eye}}"
|
||||||
Command="{Binding ToggleForwardedEmailHiddenValueCommand}"
|
Command="{Binding ToggleForwardedEmailHiddenValueCommand}"
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Grid.Column="1"/>
|
Grid.Column="1"/>
|
||||||
@@ -462,7 +505,7 @@
|
|||||||
StyleClass="box-value"
|
StyleClass="box-value"
|
||||||
HorizontalOptions="End"
|
HorizontalOptions="End"
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
AutomationProperties.Name="{u:I18n LowercaseAtoZ}" />
|
AutomationProperties.Name="{u:I18n LowercaseAtoZ}"/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<BoxView StyleClass="box-row-separator" />
|
<BoxView StyleClass="box-row-separator" />
|
||||||
<StackLayout StyleClass="box-row, box-row-switch">
|
<StackLayout StyleClass="box-row, box-row-switch">
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ namespace Bit.App.Pages
|
|||||||
private bool _showFirefoxRelayApiAccessToken;
|
private bool _showFirefoxRelayApiAccessToken;
|
||||||
private bool _showAnonAddyApiAccessToken;
|
private bool _showAnonAddyApiAccessToken;
|
||||||
private bool _showSimpleLoginApiKey;
|
private bool _showSimpleLoginApiKey;
|
||||||
|
private bool _showDuckDuckGoApiKey;
|
||||||
|
private bool _showFastmailApiKey;
|
||||||
private bool _editMode;
|
private bool _editMode;
|
||||||
|
|
||||||
public GeneratorPageViewModel()
|
public GeneratorPageViewModel()
|
||||||
@@ -79,6 +81,8 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
ForwardedEmailServiceTypeOptions = new List<ForwardedEmailServiceType> {
|
ForwardedEmailServiceTypeOptions = new List<ForwardedEmailServiceType> {
|
||||||
ForwardedEmailServiceType.AnonAddy,
|
ForwardedEmailServiceType.AnonAddy,
|
||||||
|
ForwardedEmailServiceType.DuckDuckGo,
|
||||||
|
ForwardedEmailServiceType.Fastmail,
|
||||||
ForwardedEmailServiceType.FirefoxRelay,
|
ForwardedEmailServiceType.FirefoxRelay,
|
||||||
ForwardedEmailServiceType.SimpleLogin
|
ForwardedEmailServiceType.SimpleLogin
|
||||||
};
|
};
|
||||||
@@ -461,15 +465,9 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
return _showAnonAddyApiAccessToken;
|
return _showAnonAddyApiAccessToken;
|
||||||
}
|
}
|
||||||
set => SetProperty(ref _showAnonAddyApiAccessToken, value,
|
set => SetProperty(ref _showAnonAddyApiAccessToken, value);
|
||||||
additionalPropertyNames: new string[]
|
|
||||||
{
|
|
||||||
nameof(ShowAnonAddyHiddenValueIcon)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ShowAnonAddyHiddenValueIcon => _showAnonAddyApiAccessToken ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
|
|
||||||
|
|
||||||
public string AnonAddyDomainName
|
public string AnonAddyDomainName
|
||||||
{
|
{
|
||||||
get => _usernameOptions.AnonAddyDomainName;
|
get => _usernameOptions.AnonAddyDomainName;
|
||||||
@@ -504,15 +502,9 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
return _showFirefoxRelayApiAccessToken;
|
return _showFirefoxRelayApiAccessToken;
|
||||||
}
|
}
|
||||||
set => SetProperty(ref _showFirefoxRelayApiAccessToken, value,
|
set => SetProperty(ref _showFirefoxRelayApiAccessToken, value);
|
||||||
additionalPropertyNames: new string[]
|
|
||||||
{
|
|
||||||
nameof(ShowFirefoxRelayHiddenValueIcon)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ShowFirefoxRelayHiddenValueIcon => _showFirefoxRelayApiAccessToken ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
|
|
||||||
|
|
||||||
public string SimpleLoginApiKey
|
public string SimpleLoginApiKey
|
||||||
{
|
{
|
||||||
get => _usernameOptions.SimpleLoginApiKey;
|
get => _usernameOptions.SimpleLoginApiKey;
|
||||||
@@ -533,14 +525,55 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
return _showSimpleLoginApiKey;
|
return _showSimpleLoginApiKey;
|
||||||
}
|
}
|
||||||
set => SetProperty(ref _showSimpleLoginApiKey, value,
|
set => SetProperty(ref _showSimpleLoginApiKey, value);
|
||||||
additionalPropertyNames: new string[]
|
|
||||||
{
|
|
||||||
nameof(ShowSimpleLoginHiddenValueIcon)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ShowSimpleLoginHiddenValueIcon => _showSimpleLoginApiKey ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
|
public string DuckDuckGoApiKey
|
||||||
|
{
|
||||||
|
get => _usernameOptions.DuckDuckGoApiKey;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_usernameOptions.DuckDuckGoApiKey != value)
|
||||||
|
{
|
||||||
|
_usernameOptions.DuckDuckGoApiKey = value;
|
||||||
|
TriggerPropertyChanged(nameof(DuckDuckGoApiKey));
|
||||||
|
SaveUsernameOptionsAsync(false).FireAndForget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShowDuckDuckGoApiKey
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _showDuckDuckGoApiKey;
|
||||||
|
}
|
||||||
|
set => SetProperty(ref _showDuckDuckGoApiKey, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string FastmailApiKey
|
||||||
|
{
|
||||||
|
get => _usernameOptions.FastMailApiKey;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_usernameOptions.FastMailApiKey != value)
|
||||||
|
{
|
||||||
|
_usernameOptions.FastMailApiKey = value;
|
||||||
|
TriggerPropertyChanged(nameof(FastmailApiKey));
|
||||||
|
SaveUsernameOptionsAsync(false).FireAndForget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShowFastmailApiKey
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _showFastmailApiKey;
|
||||||
|
}
|
||||||
|
set => SetProperty(ref _showFastmailApiKey, value);
|
||||||
|
}
|
||||||
|
|
||||||
public bool CapitalizeRandomWordUsername
|
public bool CapitalizeRandomWordUsername
|
||||||
{
|
{
|
||||||
@@ -778,6 +811,8 @@ namespace Bit.App.Pages
|
|||||||
TriggerPropertyChanged(nameof(FirefoxRelayApiAccessToken));
|
TriggerPropertyChanged(nameof(FirefoxRelayApiAccessToken));
|
||||||
TriggerPropertyChanged(nameof(AnonAddyDomainName));
|
TriggerPropertyChanged(nameof(AnonAddyDomainName));
|
||||||
TriggerPropertyChanged(nameof(AnonAddyApiAccessToken));
|
TriggerPropertyChanged(nameof(AnonAddyApiAccessToken));
|
||||||
|
TriggerPropertyChanged(nameof(DuckDuckGoApiKey));
|
||||||
|
TriggerPropertyChanged(nameof(FastmailApiKey));
|
||||||
TriggerPropertyChanged(nameof(CatchAllEmailDomain));
|
TriggerPropertyChanged(nameof(CatchAllEmailDomain));
|
||||||
TriggerPropertyChanged(nameof(ForwardedEmailServiceSelected));
|
TriggerPropertyChanged(nameof(ForwardedEmailServiceSelected));
|
||||||
TriggerPropertyChanged(nameof(UsernameTypeSelected));
|
TriggerPropertyChanged(nameof(UsernameTypeSelected));
|
||||||
@@ -849,6 +884,12 @@ namespace Bit.App.Pages
|
|||||||
case ForwardedEmailServiceType.SimpleLogin:
|
case ForwardedEmailServiceType.SimpleLogin:
|
||||||
ShowSimpleLoginApiKey = !ShowSimpleLoginApiKey;
|
ShowSimpleLoginApiKey = !ShowSimpleLoginApiKey;
|
||||||
break;
|
break;
|
||||||
|
case ForwardedEmailServiceType.DuckDuckGo:
|
||||||
|
ShowDuckDuckGoApiKey = !ShowDuckDuckGoApiKey;
|
||||||
|
break;
|
||||||
|
case ForwardedEmailServiceType.Fastmail:
|
||||||
|
ShowFastmailApiKey = !ShowFastmailApiKey;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@
|
|||||||
Margin="0, 12, 0, 0"
|
Margin="0, 12, 0, 0"
|
||||||
HasShadow="False"
|
HasShadow="False"
|
||||||
BackgroundColor="Transparent"
|
BackgroundColor="Transparent"
|
||||||
BorderColor="Accent">
|
BorderColor="{DynamicResource PrimaryColor}">
|
||||||
<Label
|
<Label
|
||||||
Text="{u:I18n SendDisabledWarning}"
|
Text="{u:I18n SendDisabledWarning}"
|
||||||
StyleClass="text-muted, text-sm, text-bold"
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
Margin="0, 12, 0, 0"
|
Margin="0, 12, 0, 0"
|
||||||
HasShadow="False"
|
HasShadow="False"
|
||||||
BackgroundColor="Transparent"
|
BackgroundColor="Transparent"
|
||||||
BorderColor="Accent">
|
BorderColor="{DynamicResource PrimaryColor}">
|
||||||
<Label
|
<Label
|
||||||
Text="{u:I18n SendOptionsPolicyInEffect}"
|
Text="{u:I18n SendOptionsPolicyInEffect}"
|
||||||
StyleClass="text-muted, text-sm, text-bold"
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
Margin="0, 12, 0, 0"
|
Margin="0, 12, 0, 0"
|
||||||
HasShadow="False"
|
HasShadow="False"
|
||||||
BackgroundColor="Transparent"
|
BackgroundColor="Transparent"
|
||||||
BorderColor="Accent">
|
BorderColor="{DynamicResource PrimaryColor}">
|
||||||
<Label
|
<Label
|
||||||
Text="{u:I18n SendDisabledWarning}"
|
Text="{u:I18n SendDisabledWarning}"
|
||||||
StyleClass="text-muted, text-sm, text-bold"
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
Margin="0, 12, 0, 0"
|
Margin="0, 12, 0, 0"
|
||||||
HasShadow="False"
|
HasShadow="False"
|
||||||
BackgroundColor="Transparent"
|
BackgroundColor="Transparent"
|
||||||
BorderColor="Accent">
|
BorderColor="{DynamicResource PrimaryColor}">
|
||||||
<Label
|
<Label
|
||||||
Text="{u:I18n SendOptionsPolicyInEffect}"
|
Text="{u:I18n SendOptionsPolicyInEffect}"
|
||||||
StyleClass="text-muted, text-sm, text-bold"
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
|
|||||||
@@ -108,7 +108,7 @@
|
|||||||
Margin="0, 12, 0, 6"
|
Margin="0, 12, 0, 6"
|
||||||
HasShadow="False"
|
HasShadow="False"
|
||||||
BackgroundColor="Transparent"
|
BackgroundColor="Transparent"
|
||||||
BorderColor="Accent">
|
BorderColor="{DynamicResource PrimaryColor}">
|
||||||
<Label
|
<Label
|
||||||
Text="{u:I18n SendDisabledWarning}"
|
Text="{u:I18n SendDisabledWarning}"
|
||||||
StyleClass="text-muted, text-sm, text-bold"
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
Margin="0, 12, 0, 0"
|
Margin="0, 12, 0, 0"
|
||||||
HasShadow="False"
|
HasShadow="False"
|
||||||
BackgroundColor="Transparent"
|
BackgroundColor="Transparent"
|
||||||
BorderColor="Accent">
|
BorderColor="{DynamicResource PrimaryColor}">
|
||||||
<Label
|
<Label
|
||||||
Text="{u:I18n DisablePersonalVaultExportPolicyInEffect}"
|
Text="{u:I18n DisablePersonalVaultExportPolicyInEffect}"
|
||||||
StyleClass="text-muted, text-sm, text-bold"
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
|
|||||||
107
src/App/Pages/Settings/LoginPasswordlessRequestsListPage.xaml
Normal file
107
src/App/Pages/Settings/LoginPasswordlessRequestsListPage.xaml
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<pages:BaseContentPage
|
||||||
|
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
|
||||||
|
x:Class="Bit.App.Pages.LoginPasswordlessRequestsListPage"
|
||||||
|
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||||
|
x:DataType="pages:LoginPasswordlessRequestsListViewModel"
|
||||||
|
xmlns:models="clr-namespace:Bit.Core.Models.Response;assembly=BitwardenCore"
|
||||||
|
xmlns:core="clr-namespace:Bit.Core;assembly=BitwardenCore"
|
||||||
|
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||||
|
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||||
|
Title="{Binding PageTitle}">
|
||||||
|
|
||||||
|
<ContentPage.BindingContext>
|
||||||
|
<pages:LoginPasswordlessRequestsListViewModel />
|
||||||
|
</ContentPage.BindingContext>
|
||||||
|
|
||||||
|
<ContentPage.ToolbarItems>
|
||||||
|
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
|
||||||
|
</ContentPage.ToolbarItems>
|
||||||
|
|
||||||
|
<ContentPage.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<u:DateTimeConverter x:Key="dateTime" />
|
||||||
|
<xct:ItemSelectedEventArgsConverter x:Key="ItemSelectedEventArgsConverter" />
|
||||||
|
<controls:SelectionChangedEventArgsConverter x:Key="SelectionChangedEventArgsConverter" />
|
||||||
|
<DataTemplate
|
||||||
|
x:Key="loginRequestTemplate"
|
||||||
|
x:DataType="models:PasswordlessLoginResponse">
|
||||||
|
<Grid
|
||||||
|
Padding="10, 0"
|
||||||
|
RowSpacing="0"
|
||||||
|
RowDefinitions="*, Auto, *, 10"
|
||||||
|
ColumnDefinitions="*, *">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n FingerprintPhrase}"
|
||||||
|
FontSize="Small"
|
||||||
|
Padding="0, 10, 0 ,0"
|
||||||
|
FontAttributes="Bold"/>
|
||||||
|
<controls:MonoLabel
|
||||||
|
FormattedText="{Binding RequestFingerprint}"
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
FontSize="Small"
|
||||||
|
Padding="0, 5, 0, 10"
|
||||||
|
VerticalTextAlignment="Center"
|
||||||
|
TextColor="{DynamicResource FingerprintPhrase}"/>
|
||||||
|
<Label
|
||||||
|
Grid.Row="2"
|
||||||
|
HorizontalOptions="Start"
|
||||||
|
HorizontalTextAlignment="Start"
|
||||||
|
Text="{Binding RequestDeviceType}"
|
||||||
|
StyleClass="list-header-sub" />
|
||||||
|
<Label
|
||||||
|
Grid.Row="2"
|
||||||
|
Grid.Column="1"
|
||||||
|
HorizontalOptions="End"
|
||||||
|
HorizontalTextAlignment="End"
|
||||||
|
Text="{Binding CreationDate, Converter={StaticResource dateTime}}"
|
||||||
|
StyleClass="list-header-sub" />
|
||||||
|
<BoxView
|
||||||
|
StyleClass="list-section-separator-top, list-section-separator-top-platform"
|
||||||
|
VerticalOptions="End"
|
||||||
|
Grid.Row="3"
|
||||||
|
Grid.ColumnSpan="2"/>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
|
||||||
|
<StackLayout
|
||||||
|
x:Key="mainLayout"
|
||||||
|
x:Name="_mainLayout"
|
||||||
|
Padding="0, 10">
|
||||||
|
<RefreshView
|
||||||
|
IsRefreshing="{Binding IsRefreshing}"
|
||||||
|
Command="{Binding RefreshCommand}"
|
||||||
|
VerticalOptions="FillAndExpand"
|
||||||
|
BackgroundColor="{DynamicResource BackgroundColor}">
|
||||||
|
<controls:ExtendedCollectionView
|
||||||
|
ItemsSource="{Binding LoginRequests}"
|
||||||
|
ItemTemplate="{StaticResource loginRequestTemplate}"
|
||||||
|
SelectionMode="Single"
|
||||||
|
ExtraDataForLogging="Login requests page" >
|
||||||
|
<controls:ExtendedCollectionView.Behaviors>
|
||||||
|
<xct:EventToCommandBehavior
|
||||||
|
EventName="SelectionChanged"
|
||||||
|
Command="{Binding AnswerRequestCommand}"
|
||||||
|
EventArgsConverter="{StaticResource SelectionChangedEventArgsConverter}" />
|
||||||
|
</controls:ExtendedCollectionView.Behaviors>
|
||||||
|
</controls:ExtendedCollectionView>
|
||||||
|
</RefreshView>
|
||||||
|
<controls:IconLabelButton
|
||||||
|
VerticalOptions="End"
|
||||||
|
Margin="10,0"
|
||||||
|
Icon="{Binding Source={x:Static core:BitwardenIcons.Trash}}"
|
||||||
|
Label="{u:I18n DeclineAllRequests}"
|
||||||
|
ButtonCommand="{Binding DeclineAllRequestsCommand}"/>
|
||||||
|
</StackLayout>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</ContentPage.Resources>
|
||||||
|
|
||||||
|
<ContentView
|
||||||
|
x:Name="_mainContent">
|
||||||
|
</ContentView>
|
||||||
|
|
||||||
|
</pages:BaseContentPage>
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Models.Response;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Bit.App.Pages
|
||||||
|
{
|
||||||
|
public partial class LoginPasswordlessRequestsListPage : BaseContentPage
|
||||||
|
{
|
||||||
|
private LoginPasswordlessRequestsListViewModel _vm;
|
||||||
|
|
||||||
|
public LoginPasswordlessRequestsListPage()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
SetActivityIndicator(_mainContent);
|
||||||
|
_vm = BindingContext as LoginPasswordlessRequestsListViewModel;
|
||||||
|
_vm.Page = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async void OnAppearing()
|
||||||
|
{
|
||||||
|
base.OnAppearing();
|
||||||
|
await LoadOnAppearedAsync(_mainLayout, false, _vm.RefreshAsync, _mainContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void Close_Clicked(object sender, System.EventArgs e)
|
||||||
|
{
|
||||||
|
if (DoOnce())
|
||||||
|
{
|
||||||
|
await Navigation.PopModalAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
139
src/App/Pages/Settings/LoginPasswordlessRequestsListViewModel.cs
Normal file
139
src/App/Pages/Settings/LoginPasswordlessRequestsListViewModel.cs
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using Bit.App.Abstractions;
|
||||||
|
using Bit.App.Resources;
|
||||||
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Models.Response;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
using Xamarin.CommunityToolkit.ObjectModel;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Bit.App.Pages
|
||||||
|
{
|
||||||
|
public class LoginPasswordlessRequestsListViewModel : BaseViewModel
|
||||||
|
{
|
||||||
|
private readonly IAuthService _authService;
|
||||||
|
private readonly IStateService _stateService;
|
||||||
|
private readonly IDeviceActionService _deviceActionService;
|
||||||
|
private readonly IPlatformUtilsService _platformUtilsService;
|
||||||
|
private bool _isRefreshing;
|
||||||
|
|
||||||
|
public LoginPasswordlessRequestsListViewModel()
|
||||||
|
{
|
||||||
|
_authService = ServiceContainer.Resolve<IAuthService>();
|
||||||
|
_stateService = ServiceContainer.Resolve<IStateService>();
|
||||||
|
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>();
|
||||||
|
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>();
|
||||||
|
|
||||||
|
PageTitle = AppResources.PendingLogInRequests;
|
||||||
|
LoginRequests = new ObservableRangeCollection<PasswordlessLoginResponse>();
|
||||||
|
|
||||||
|
AnswerRequestCommand = new AsyncCommand<PasswordlessLoginResponse>(PasswordlessLoginAsync,
|
||||||
|
onException: ex => HandleException(ex),
|
||||||
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
|
DeclineAllRequestsCommand = new AsyncCommand(DeclineAllRequestsAsync,
|
||||||
|
onException: ex => HandleException(ex),
|
||||||
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
|
RefreshCommand = new Command(async () => await RefreshAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICommand RefreshCommand { get; }
|
||||||
|
|
||||||
|
public AsyncCommand<PasswordlessLoginResponse> AnswerRequestCommand { get; }
|
||||||
|
|
||||||
|
public AsyncCommand DeclineAllRequestsCommand { get; }
|
||||||
|
|
||||||
|
public ObservableRangeCollection<PasswordlessLoginResponse> LoginRequests { get; }
|
||||||
|
|
||||||
|
public bool IsRefreshing
|
||||||
|
{
|
||||||
|
get => _isRefreshing;
|
||||||
|
set => SetProperty(ref _isRefreshing, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RefreshAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IsRefreshing = true;
|
||||||
|
LoginRequests.ReplaceRange(await _authService.GetActivePasswordlessLoginRequestsAsync());
|
||||||
|
if (!LoginRequests.Any())
|
||||||
|
{
|
||||||
|
Page.Navigation.PopModalAsync().FireAndForget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
HandleException(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
IsRefreshing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task PasswordlessLoginAsync(PasswordlessLoginResponse request)
|
||||||
|
{
|
||||||
|
if (request.IsExpired)
|
||||||
|
{
|
||||||
|
await _platformUtilsService.ShowDialogAsync(AppResources.LoginRequestHasAlreadyExpired);
|
||||||
|
await Page.Navigation.PopModalAsync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var loginRequestData = await _authService.GetPasswordlessLoginRequestByIdAsync(request.Id);
|
||||||
|
if (loginRequestData.IsAnswered)
|
||||||
|
{
|
||||||
|
await _platformUtilsService.ShowDialogAsync(AppResources.ThisRequestIsNoLongerValid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var page = new LoginPasswordlessPage(new LoginPasswordlessDetails()
|
||||||
|
{
|
||||||
|
PubKey = loginRequestData.PublicKey,
|
||||||
|
Id = loginRequestData.Id,
|
||||||
|
IpAddress = loginRequestData.RequestIpAddress,
|
||||||
|
Email = await _stateService.GetEmailAsync(),
|
||||||
|
FingerprintPhrase = loginRequestData.RequestFingerprint,
|
||||||
|
RequestDate = loginRequestData.CreationDate,
|
||||||
|
DeviceType = loginRequestData.RequestDeviceType,
|
||||||
|
Origin = loginRequestData.Origin
|
||||||
|
});
|
||||||
|
|
||||||
|
await Device.InvokeOnMainThreadAsync(() => Application.Current.MainPage.Navigation.PushModalAsync(new NavigationPage(page)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DeclineAllRequestsAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!await _platformUtilsService.ShowDialogAsync(AppResources.AreYouSureYouWantToDeclineAllPendingLogInRequests, null, AppResources.Yes, AppResources.No))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _deviceActionService.ShowLoadingAsync(AppResources.Loading);
|
||||||
|
var taskList = new List<Task>();
|
||||||
|
foreach (var request in LoginRequests)
|
||||||
|
{
|
||||||
|
taskList.Add(_authService.PasswordlessLoginAsync(request.Id, request.PublicKey, false));
|
||||||
|
}
|
||||||
|
await Task.WhenAll(taskList);
|
||||||
|
await _deviceActionService.HideLoadingAsync();
|
||||||
|
await RefreshAsync();
|
||||||
|
_platformUtilsService.ShowToast("info", null, AppResources.RequestsDeclined);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
HandleException(ex);
|
||||||
|
RefreshAsync().FireAndForget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
Padding="10"
|
Padding="10"
|
||||||
HasShadow="False"
|
HasShadow="False"
|
||||||
BackgroundColor="Transparent"
|
BackgroundColor="Transparent"
|
||||||
BorderColor="Accent">
|
BorderColor="{DynamicResource PrimaryColor}">
|
||||||
<Label
|
<Label
|
||||||
Text="{Binding Name, Mode=OneWay}"
|
Text="{Binding Name, Mode=OneWay}"
|
||||||
StyleClass="text-muted, text-sm, text-bold"
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
Padding="10"
|
Padding="10"
|
||||||
HasShadow="False"
|
HasShadow="False"
|
||||||
BackgroundColor="Transparent"
|
BackgroundColor="Transparent"
|
||||||
BorderColor="Accent">
|
BorderColor="{DynamicResource PrimaryColor}">
|
||||||
<Label
|
<Label
|
||||||
Text="{Binding Name, Mode=OneWay}"
|
Text="{Binding Name, Mode=OneWay}"
|
||||||
StyleClass="text-muted, text-sm, text-bold"
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ using Bit.App.Pages.Accounts;
|
|||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models;
|
||||||
using Bit.Core.Models.Domain;
|
using Bit.Core.Models.Domain;
|
||||||
|
using Bit.Core.Models.Response;
|
||||||
|
using Bit.Core.Models.View;
|
||||||
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Xamarin.CommunityToolkit.ObjectModel;
|
using Xamarin.CommunityToolkit.ObjectModel;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
@@ -32,6 +36,8 @@ namespace Bit.App.Pages
|
|||||||
private readonly IClipboardService _clipboardService;
|
private readonly IClipboardService _clipboardService;
|
||||||
private readonly ILogger _loggerService;
|
private readonly ILogger _loggerService;
|
||||||
private readonly IPushNotificationService _pushNotificationService;
|
private readonly IPushNotificationService _pushNotificationService;
|
||||||
|
private readonly IAuthService _authService;
|
||||||
|
private readonly IWatchDeviceService _watchDeviceService;
|
||||||
private const int CustomVaultTimeoutValue = -100;
|
private const int CustomVaultTimeoutValue = -100;
|
||||||
|
|
||||||
private bool _supportsBiometric;
|
private bool _supportsBiometric;
|
||||||
@@ -44,7 +50,7 @@ namespace Bit.App.Pages
|
|||||||
private bool _showChangeMasterPassword;
|
private bool _showChangeMasterPassword;
|
||||||
private bool _reportLoggingEnabled;
|
private bool _reportLoggingEnabled;
|
||||||
private bool _approvePasswordlessLoginRequests;
|
private bool _approvePasswordlessLoginRequests;
|
||||||
|
private bool _shouldConnectToWatch;
|
||||||
private List<KeyValuePair<string, int?>> _vaultTimeouts =
|
private List<KeyValuePair<string, int?>> _vaultTimeouts =
|
||||||
new List<KeyValuePair<string, int?>>
|
new List<KeyValuePair<string, int?>>
|
||||||
{
|
{
|
||||||
@@ -87,7 +93,8 @@ namespace Bit.App.Pages
|
|||||||
_clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
|
_clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
|
||||||
_loggerService = ServiceContainer.Resolve<ILogger>("logger");
|
_loggerService = ServiceContainer.Resolve<ILogger>("logger");
|
||||||
_pushNotificationService = ServiceContainer.Resolve<IPushNotificationService>();
|
_pushNotificationService = ServiceContainer.Resolve<IPushNotificationService>();
|
||||||
|
_authService = ServiceContainer.Resolve<IAuthService>();
|
||||||
|
_watchDeviceService = ServiceContainer.Resolve<IWatchDeviceService>();
|
||||||
GroupedItems = new ObservableRangeCollection<ISettingsPageListItem>();
|
GroupedItems = new ObservableRangeCollection<ISettingsPageListItem>();
|
||||||
PageTitle = AppResources.Settings;
|
PageTitle = AppResources.Settings;
|
||||||
|
|
||||||
@@ -138,6 +145,8 @@ namespace Bit.App.Pages
|
|||||||
!await _keyConnectorService.GetUsesKeyConnector();
|
!await _keyConnectorService.GetUsesKeyConnector();
|
||||||
_reportLoggingEnabled = await _loggerService.IsEnabled();
|
_reportLoggingEnabled = await _loggerService.IsEnabled();
|
||||||
_approvePasswordlessLoginRequests = await _stateService.GetApprovePasswordlessLoginsAsync();
|
_approvePasswordlessLoginRequests = await _stateService.GetApprovePasswordlessLoginsAsync();
|
||||||
|
_shouldConnectToWatch = await _stateService.GetShouldConnectToWatchAsync();
|
||||||
|
|
||||||
BuildList();
|
BuildList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,12 +422,9 @@ namespace Bit.App.Pages
|
|||||||
AppResources.Yes, AppResources.No);
|
AppResources.Yes, AppResources.No);
|
||||||
}
|
}
|
||||||
|
|
||||||
var kdf = await _stateService.GetKdfTypeAsync();
|
var kdfConfig = await _stateService.GetActiveUserCustomDataAsync(a => new KdfConfig(a?.Profile));
|
||||||
var kdfIterations = await _stateService.GetKdfIterationsAsync();
|
|
||||||
var email = await _stateService.GetEmailAsync();
|
var email = await _stateService.GetEmailAsync();
|
||||||
var pinKey = await _cryptoService.MakePinKeyAysnc(pin, email,
|
var pinKey = await _cryptoService.MakePinKeyAysnc(pin, email, kdfConfig);
|
||||||
kdf.GetValueOrDefault(Core.Enums.KdfType.PBKDF2_SHA256),
|
|
||||||
kdfIterations.GetValueOrDefault(5000));
|
|
||||||
var key = await _cryptoService.GetKeyAsync();
|
var key = await _cryptoService.GetKeyAsync();
|
||||||
var pinProtectedKey = await _cryptoService.EncryptAsync(key.Key, pinKey);
|
var pinProtectedKey = await _cryptoService.EncryptAsync(key.Key, pinKey);
|
||||||
|
|
||||||
@@ -557,6 +563,14 @@ namespace Bit.App.Pages
|
|||||||
ExecuteAsync = () => TwoStepAsync()
|
ExecuteAsync = () => TwoStepAsync()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
if (_approvePasswordlessLoginRequests)
|
||||||
|
{
|
||||||
|
manageItems.Add(new SettingsPageListItem
|
||||||
|
{
|
||||||
|
Name = AppResources.PendingLogInRequests,
|
||||||
|
ExecuteAsync = () => PendingLoginRequestsAsync()
|
||||||
|
});
|
||||||
|
}
|
||||||
if (_supportsBiometric || _biometric)
|
if (_supportsBiometric || _biometric)
|
||||||
{
|
{
|
||||||
var biometricName = AppResources.Biometrics;
|
var biometricName = AppResources.Biometrics;
|
||||||
@@ -601,19 +615,26 @@ namespace Bit.App.Pages
|
|||||||
ExecuteAsync = () => SetScreenCaptureAllowedAsync()
|
ExecuteAsync = () => SetScreenCaptureAllowedAsync()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
var accountItems = new List<SettingsPageListItem>
|
var accountItems = new List<SettingsPageListItem>();
|
||||||
|
if (Device.RuntimePlatform == Device.iOS)
|
||||||
{
|
{
|
||||||
new SettingsPageListItem
|
accountItems.Add(new SettingsPageListItem
|
||||||
{
|
{
|
||||||
Name = AppResources.FingerprintPhrase,
|
Name = AppResources.ConnectToWatch,
|
||||||
ExecuteAsync = () => FingerprintAsync()
|
SubLabel = _shouldConnectToWatch ? AppResources.On : AppResources.Off,
|
||||||
},
|
ExecuteAsync = () => ToggleWatchConnectionAsync()
|
||||||
new SettingsPageListItem
|
});
|
||||||
{
|
}
|
||||||
Name = AppResources.LogOut,
|
accountItems.Add(new SettingsPageListItem
|
||||||
ExecuteAsync = () => LogOutAsync()
|
{
|
||||||
}
|
Name = AppResources.FingerprintPhrase,
|
||||||
};
|
ExecuteAsync = () => FingerprintAsync()
|
||||||
|
});
|
||||||
|
accountItems.Add(new SettingsPageListItem
|
||||||
|
{
|
||||||
|
Name = AppResources.LogOut,
|
||||||
|
ExecuteAsync = () => LogOutAsync()
|
||||||
|
});
|
||||||
if (_showChangeMasterPassword)
|
if (_showChangeMasterPassword)
|
||||||
{
|
{
|
||||||
accountItems.Insert(0, new SettingsPageListItem
|
accountItems.Insert(0, new SettingsPageListItem
|
||||||
@@ -741,6 +762,25 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task PendingLoginRequestsAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var requests = await _authService.GetActivePasswordlessLoginRequestsAsync();
|
||||||
|
if (requests == null || !requests.Any())
|
||||||
|
{
|
||||||
|
_platformUtilsService.ShowToast("info", null, AppResources.NoPendingRequests);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Page.Navigation.PushModalAsync(new NavigationPage(new LoginPasswordlessRequestsListPage())).FireAndForget();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
HandleException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool IncludeLinksWithSubscriptionInfo()
|
private bool IncludeLinksWithSubscriptionInfo()
|
||||||
{
|
{
|
||||||
if (Device.RuntimePlatform == Device.iOS)
|
if (Device.RuntimePlatform == Device.iOS)
|
||||||
@@ -791,5 +831,13 @@ namespace Bit.App.Pages
|
|||||||
await Page.DisplayAlert(AppResources.AnErrorHasOccurred, AppResources.GenericErrorMessage, AppResources.Ok);
|
await Page.DisplayAlert(AppResources.AnErrorHasOccurred, AppResources.GenericErrorMessage, AppResources.Ok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ToggleWatchConnectionAsync()
|
||||||
|
{
|
||||||
|
_shouldConnectToWatch = !_shouldConnectToWatch;
|
||||||
|
|
||||||
|
await _watchDeviceService.SetShouldConnectToWatchAsync(_shouldConnectToWatch);
|
||||||
|
BuildList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@
|
|||||||
Margin="0"
|
Margin="0"
|
||||||
HasShadow="False"
|
HasShadow="False"
|
||||||
BackgroundColor="Transparent"
|
BackgroundColor="Transparent"
|
||||||
BorderColor="Accent">
|
BorderColor="{DynamicResource PrimaryColor}">
|
||||||
<Label
|
<Label
|
||||||
Text="{u:I18n PersonalOwnershipPolicyInEffect}"
|
Text="{u:I18n PersonalOwnershipPolicyInEffect}"
|
||||||
StyleClass="text-muted, text-sm, text-bold"
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
|
|||||||
@@ -263,12 +263,6 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
if (DoOnce())
|
if (DoOnce())
|
||||||
{
|
{
|
||||||
var cameraPermission = await PermissionManager.CheckAndRequestPermissionAsync(new Permissions.Camera());
|
|
||||||
if (cameraPermission != PermissionStatus.Granted)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var page = new ScanPage(key =>
|
var page = new ScanPage(key =>
|
||||||
{
|
{
|
||||||
Device.BeginInvokeOnMainThread(async () =>
|
Device.BeginInvokeOnMainThread(async () =>
|
||||||
@@ -277,6 +271,7 @@ namespace Bit.App.Pages
|
|||||||
await _vm.UpdateTotpKeyAsync(key);
|
await _vm.UpdateTotpKeyAsync(key);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
await Navigation.PushModalAsync(new Xamarin.Forms.NavigationPage(page));
|
await Navigation.PushModalAsync(new Xamarin.Forms.NavigationPage(page));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace Bit.App.Pages
|
|||||||
private readonly ICustomFieldItemFactory _customFieldItemFactory;
|
private readonly ICustomFieldItemFactory _customFieldItemFactory;
|
||||||
private readonly IClipboardService _clipboardService;
|
private readonly IClipboardService _clipboardService;
|
||||||
private readonly IAutofillHandler _autofillHandler;
|
private readonly IAutofillHandler _autofillHandler;
|
||||||
|
private readonly IWatchDeviceService _watchDeviceService;
|
||||||
|
|
||||||
private bool _showNotesSeparator;
|
private bool _showNotesSeparator;
|
||||||
private bool _showPassword;
|
private bool _showPassword;
|
||||||
@@ -80,6 +81,7 @@ namespace Bit.App.Pages
|
|||||||
_customFieldItemFactory = ServiceContainer.Resolve<ICustomFieldItemFactory>("customFieldItemFactory");
|
_customFieldItemFactory = ServiceContainer.Resolve<ICustomFieldItemFactory>("customFieldItemFactory");
|
||||||
_clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
|
_clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
|
||||||
_autofillHandler = ServiceContainer.Resolve<IAutofillHandler>();
|
_autofillHandler = ServiceContainer.Resolve<IAutofillHandler>();
|
||||||
|
_watchDeviceService = ServiceContainer.Resolve<IWatchDeviceService>();
|
||||||
|
|
||||||
GeneratePasswordCommand = new Command(GeneratePassword);
|
GeneratePasswordCommand = new Command(GeneratePassword);
|
||||||
TogglePasswordCommand = new Command(TogglePassword);
|
TogglePasswordCommand = new Command(TogglePassword);
|
||||||
@@ -137,6 +139,7 @@ namespace Bit.App.Pages
|
|||||||
new KeyValuePair<string, string>(AppResources.Mr, AppResources.Mr),
|
new KeyValuePair<string, string>(AppResources.Mr, AppResources.Mr),
|
||||||
new KeyValuePair<string, string>(AppResources.Mrs, AppResources.Mrs),
|
new KeyValuePair<string, string>(AppResources.Mrs, AppResources.Mrs),
|
||||||
new KeyValuePair<string, string>(AppResources.Ms, AppResources.Ms),
|
new KeyValuePair<string, string>(AppResources.Ms, AppResources.Ms),
|
||||||
|
new KeyValuePair<string, string>(AppResources.Mx, AppResources.Mx),
|
||||||
new KeyValuePair<string, string>(AppResources.Dr, AppResources.Dr),
|
new KeyValuePair<string, string>(AppResources.Dr, AppResources.Dr),
|
||||||
};
|
};
|
||||||
FolderOptions = new List<KeyValuePair<string, string>>();
|
FolderOptions = new List<KeyValuePair<string, string>>();
|
||||||
@@ -507,6 +510,8 @@ namespace Bit.App.Pages
|
|||||||
EditMode && !CloneMode ? AppResources.ItemUpdated : AppResources.NewItemCreated);
|
EditMode && !CloneMode ? AppResources.ItemUpdated : AppResources.NewItemCreated);
|
||||||
_messagingService.Send(EditMode && !CloneMode ? "editedCipher" : "addedCipher", Cipher.Id);
|
_messagingService.Send(EditMode && !CloneMode ? "editedCipher" : "addedCipher", Cipher.Id);
|
||||||
|
|
||||||
|
_watchDeviceService.SyncDataToWatchAsync().FireAndForget();
|
||||||
|
|
||||||
if (Page is CipherAddEditPage page && page.FromAutofillFramework)
|
if (Page is CipherAddEditPage page && page.FromAutofillFramework)
|
||||||
{
|
{
|
||||||
// Close and go back to app
|
// Close and go back to app
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ namespace Bit.App.Pages
|
|||||||
private readonly ILocalizeService _localizeService;
|
private readonly ILocalizeService _localizeService;
|
||||||
private readonly ICustomFieldItemFactory _customFieldItemFactory;
|
private readonly ICustomFieldItemFactory _customFieldItemFactory;
|
||||||
private readonly IClipboardService _clipboardService;
|
private readonly IClipboardService _clipboardService;
|
||||||
|
private readonly IWatchDeviceService _watchDeviceService;
|
||||||
|
|
||||||
private List<ICustomFieldItemViewModel> _fields;
|
private List<ICustomFieldItemViewModel> _fields;
|
||||||
private bool _canAccessPremium;
|
private bool _canAccessPremium;
|
||||||
@@ -62,6 +63,7 @@ namespace Bit.App.Pages
|
|||||||
_localizeService = ServiceContainer.Resolve<ILocalizeService>("localizeService");
|
_localizeService = ServiceContainer.Resolve<ILocalizeService>("localizeService");
|
||||||
_customFieldItemFactory = ServiceContainer.Resolve<ICustomFieldItemFactory>("customFieldItemFactory");
|
_customFieldItemFactory = ServiceContainer.Resolve<ICustomFieldItemFactory>("customFieldItemFactory");
|
||||||
_clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
|
_clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
|
||||||
|
_watchDeviceService = ServiceContainer.Resolve<IWatchDeviceService>();
|
||||||
|
|
||||||
CopyCommand = new AsyncCommand<string>((id) => CopyAsync(id, null), onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false);
|
CopyCommand = new AsyncCommand<string>((id) => CopyAsync(id, null), onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false);
|
||||||
CopyUriCommand = new AsyncCommand<LoginUriView>(uriView => CopyAsync("LoginUri", uriView.Uri), onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false);
|
CopyUriCommand = new AsyncCommand<LoginUriView>(uriView => CopyAsync("LoginUri", uriView.Uri), onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false);
|
||||||
@@ -371,6 +373,9 @@ namespace Bit.App.Pages
|
|||||||
await _cipherService.SoftDeleteWithServerAsync(Cipher.Id);
|
await _cipherService.SoftDeleteWithServerAsync(Cipher.Id);
|
||||||
}
|
}
|
||||||
await _deviceActionService.HideLoadingAsync();
|
await _deviceActionService.HideLoadingAsync();
|
||||||
|
|
||||||
|
_watchDeviceService.SyncDataToWatchAsync().FireAndForget();
|
||||||
|
|
||||||
_platformUtilsService.ShowToast("success", null,
|
_platformUtilsService.ShowToast("success", null,
|
||||||
Cipher.IsDeleted ? AppResources.ItemDeleted : AppResources.ItemSoftDeleted);
|
Cipher.IsDeleted ? AppResources.ItemDeleted : AppResources.ItemSoftDeleted);
|
||||||
_messagingService.Send(Cipher.IsDeleted ? "deletedCipher" : "softDeletedCipher", Cipher);
|
_messagingService.Send(Cipher.IsDeleted ? "deletedCipher" : "softDeletedCipher", Cipher);
|
||||||
|
|||||||
@@ -108,6 +108,10 @@ namespace Bit.App.Pages
|
|||||||
else if (message.Command == "syncCompleted")
|
else if (message.Command == "syncCompleted")
|
||||||
{
|
{
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
|
if (_vm.MainPage)
|
||||||
|
{
|
||||||
|
_vm.AvatarImageSource = await GetAvatarImageSourceAsync();
|
||||||
|
}
|
||||||
Device.BeginInvokeOnMainThread(() =>
|
Device.BeginInvokeOnMainThread(() =>
|
||||||
{
|
{
|
||||||
IsBusy = false;
|
IsBusy = false;
|
||||||
|
|||||||
@@ -34,16 +34,13 @@
|
|||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<zxing:ZXingScannerView
|
<ContentView
|
||||||
x:Name="_zxing"
|
x:Name="_scannerContainer"
|
||||||
HorizontalOptions="FillAndExpand"
|
|
||||||
VerticalOptions="FillAndExpand"
|
|
||||||
AutomationId="zxingScannerView"
|
AutomationId="zxingScannerView"
|
||||||
IsVisible="{Binding ShowScanner}"
|
IsVisible="{Binding ShowScanner}"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.RowSpan="3"
|
Grid.RowSpan="3"/>
|
||||||
OnScanResult="OnScanResult"/>
|
|
||||||
<StackLayout
|
<StackLayout
|
||||||
VerticalOptions="Center"
|
VerticalOptions="Center"
|
||||||
HorizontalOptions="FillAndExpand"
|
HorizontalOptions="FillAndExpand"
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ using Bit.Core.Abstractions;
|
|||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
using SkiaSharp.Views.Forms;
|
using SkiaSharp.Views.Forms;
|
||||||
|
using Xamarin.CommunityToolkit.ObjectModel;
|
||||||
using Xamarin.Essentials;
|
using Xamarin.Essentials;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
using ZXing.Net.Mobile.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
@@ -26,20 +28,15 @@ namespace Bit.App.Pages
|
|||||||
private bool _pageIsActive;
|
private bool _pageIsActive;
|
||||||
private bool _qrcodeFound;
|
private bool _qrcodeFound;
|
||||||
private float _scale;
|
private float _scale;
|
||||||
|
private ZXingScannerView _zxing;
|
||||||
private readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>("logger");
|
private readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>("logger");
|
||||||
|
|
||||||
public ScanPage(Action<string> callback)
|
public ScanPage(Action<string> callback)
|
||||||
{
|
{
|
||||||
_callback = callback;
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_zxing.Options = new ZXing.Mobile.MobileBarcodeScanningOptions
|
_callback = callback;
|
||||||
{
|
ViewModel.InitScannerCommand = new Command(() => InitScanner());
|
||||||
UseNativeScanning = true,
|
|
||||||
PossibleFormats = new List<ZXing.BarcodeFormat> { ZXing.BarcodeFormat.QR_CODE },
|
|
||||||
AutoRotate = false,
|
|
||||||
TryInverted = true
|
|
||||||
};
|
|
||||||
if (Device.RuntimePlatform == Device.Android)
|
if (Device.RuntimePlatform == Device.Android)
|
||||||
{
|
{
|
||||||
ToolbarItems.RemoveAt(0);
|
ToolbarItems.RemoveAt(0);
|
||||||
@@ -55,6 +52,53 @@ namespace Bit.App.Pages
|
|||||||
protected override void OnAppearing()
|
protected override void OnAppearing()
|
||||||
{
|
{
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
|
StartScanner();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDisappearing()
|
||||||
|
{
|
||||||
|
StopScanner().FireAndForget();
|
||||||
|
base.OnDisappearing();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix known bug with DelayBetweenAnalyzingFrames & DelayBetweenContinuousScans: https://github.com/Redth/ZXing.Net.Mobile/issues/721
|
||||||
|
private void InitScanner()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!ViewModel.HasCameraPermission || !ViewModel.ShowScanner || _zxing != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_zxing = new ZXingScannerView();
|
||||||
|
_zxing.Options = new ZXing.Mobile.MobileBarcodeScanningOptions
|
||||||
|
{
|
||||||
|
UseNativeScanning = true,
|
||||||
|
PossibleFormats = new List<ZXing.BarcodeFormat> { ZXing.BarcodeFormat.QR_CODE },
|
||||||
|
AutoRotate = false,
|
||||||
|
TryInverted = true,
|
||||||
|
DelayBetweenAnalyzingFrames = 5,
|
||||||
|
DelayBetweenContinuousScans = 5
|
||||||
|
};
|
||||||
|
_scannerContainer.Content = _zxing;
|
||||||
|
StartScanner();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Value.Exception(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartScanner()
|
||||||
|
{
|
||||||
|
if (_zxing == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_zxing.OnScanResult -= OnScanResult;
|
||||||
|
_zxing.OnScanResult += OnScanResult;
|
||||||
_zxing.IsScanning = true;
|
_zxing.IsScanning = true;
|
||||||
|
|
||||||
// Fix for Autofocus, now it's done every 2 seconds so that the user does't have to do it
|
// Fix for Autofocus, now it's done every 2 seconds so that the user does't have to do it
|
||||||
@@ -98,16 +142,21 @@ namespace Bit.App.Pages
|
|||||||
AnimationLoopAsync();
|
AnimationLoopAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async void OnDisappearing()
|
private async Task StopScanner()
|
||||||
{
|
{
|
||||||
|
if (_zxing == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_autofocusCts?.Cancel();
|
_autofocusCts?.Cancel();
|
||||||
if (_continuousAutofocusTask != null)
|
if (_continuousAutofocusTask != null)
|
||||||
{
|
{
|
||||||
await _continuousAutofocusTask;
|
await _continuousAutofocusTask;
|
||||||
}
|
}
|
||||||
_zxing.IsScanning = false;
|
_zxing.IsScanning = false;
|
||||||
|
_zxing.OnScanResult -= OnScanResult;
|
||||||
_pageIsActive = false;
|
_pageIsActive = false;
|
||||||
base.OnDisappearing();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnScanResult(ZXing.Result result)
|
private async void OnScanResult(ZXing.Result result)
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
using Bit.App.Resources;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using Bit.App.Abstractions;
|
||||||
|
using Bit.App.Resources;
|
||||||
using Bit.App.Utilities;
|
using Bit.App.Utilities;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Services;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
using Xamarin.CommunityToolkit.ObjectModel;
|
||||||
|
using Xamarin.Essentials;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
@@ -9,13 +17,46 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
private bool _showScanner = true;
|
private bool _showScanner = true;
|
||||||
private string _totpAuthenticationKey;
|
private string _totpAuthenticationKey;
|
||||||
|
private IPlatformUtilsService _platformUtilsService;
|
||||||
|
private IDeviceActionService _deviceActionService;
|
||||||
|
private ILogger _logger;
|
||||||
|
|
||||||
public ScanPageViewModel()
|
public ScanPageViewModel()
|
||||||
{
|
{
|
||||||
ToggleScanModeCommand = new Command(() => ShowScanner = !ShowScanner);
|
ToggleScanModeCommand = new AsyncCommand(ToggleScanMode, onException: HandleException);
|
||||||
|
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
||||||
|
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||||
|
_logger = ServiceContainer.Resolve<ILogger>();
|
||||||
|
InitAsync().FireAndForget();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Command ToggleScanModeCommand { get; set; }
|
public async Task InitAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Device.InvokeOnMainThreadAsync(async () =>
|
||||||
|
{
|
||||||
|
var hasCameraPermission = await PermissionManager.CheckAndRequestPermissionAsync(new Permissions.Camera());
|
||||||
|
HasCameraPermission = hasCameraPermission == PermissionStatus.Granted;
|
||||||
|
ShowScanner = hasCameraPermission == PermissionStatus.Granted;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!HasCameraPermission)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
InitScannerCommand.Execute(null);
|
||||||
|
}
|
||||||
|
catch (System.Exception ex)
|
||||||
|
{
|
||||||
|
HandleException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICommand ToggleScanModeCommand { get; set; }
|
||||||
|
public ICommand InitScannerCommand { get; set; }
|
||||||
|
|
||||||
|
public bool HasCameraPermission { get; set; }
|
||||||
public string ScanQrPageTitle => ShowScanner ? AppResources.ScanQrTitle : AppResources.AuthenticatorKeyScanner;
|
public string ScanQrPageTitle => ShowScanner ? AppResources.ScanQrTitle : AppResources.AuthenticatorKeyScanner;
|
||||||
public string CameraInstructionTop => ShowScanner ? AppResources.PointYourCameraAtTheQRCode : AppResources.OnceTheKeyIsSuccessfullyEntered;
|
public string CameraInstructionTop => ShowScanner ? AppResources.PointYourCameraAtTheQRCode : AppResources.OnceTheKeyIsSuccessfullyEntered;
|
||||||
public string TotpAuthenticationKey
|
public string TotpAuthenticationKey
|
||||||
@@ -39,6 +80,23 @@ namespace Bit.App.Pages
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ToggleScanMode()
|
||||||
|
{
|
||||||
|
var cameraPermission = await PermissionManager.CheckAndRequestPermissionAsync(new Permissions.Camera());
|
||||||
|
HasCameraPermission = cameraPermission == PermissionStatus.Granted;
|
||||||
|
if (!HasCameraPermission)
|
||||||
|
{
|
||||||
|
var openAppSettingsResult = await _platformUtilsService.ShowDialogAsync(AppResources.EnableCamerPermissionToUseTheScanner, title: string.Empty, confirmText: AppResources.Settings, cancelText: AppResources.NoThanks);
|
||||||
|
if (openAppSettingsResult)
|
||||||
|
{
|
||||||
|
_deviceActionService.OpenAppSettings();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ShowScanner = !ShowScanner;
|
||||||
|
InitScannerCommand.Execute(null);
|
||||||
|
}
|
||||||
|
|
||||||
public FormattedString ToggleScanModeLabel
|
public FormattedString ToggleScanModeLabel
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -57,5 +115,15 @@ namespace Bit.App.Pages
|
|||||||
return fs;
|
return fs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleException(Exception ex)
|
||||||
|
{
|
||||||
|
Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
|
||||||
|
{
|
||||||
|
await _deviceActionService.HideLoadingAsync();
|
||||||
|
await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage);
|
||||||
|
}).FireAndForget();
|
||||||
|
_logger.Exception(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
215
src/App/Resources/AppResources.Designer.cs
generated
215
src/App/Resources/AppResources.Designer.cs
generated
@@ -562,6 +562,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Are you sure you want to decline all pending login requests?.
|
||||||
|
/// </summary>
|
||||||
|
public static string AreYouSureYouWantToDeclineAllPendingLogInRequests {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("AreYouSureYouWantToDeclineAllPendingLogInRequests", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Are you sure you want to turn on screen capture?.
|
/// Looks up a localized string similar to Are you sure you want to turn on screen capture?.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1372,6 +1381,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Check known data breaches for this password.
|
||||||
|
/// </summary>
|
||||||
|
public static string CheckKnownDataBreachesForThisPassword {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("CheckKnownDataBreachesForThisPassword", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Check if password has been exposed..
|
/// Looks up a localized string similar to Check if password has been exposed..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1498,6 +1516,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Connect to Watch.
|
||||||
|
/// </summary>
|
||||||
|
public static string ConnectToWatch {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ConnectToWatch", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Continue.
|
/// Looks up a localized string similar to Continue.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1741,6 +1768,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Decline all requests.
|
||||||
|
/// </summary>
|
||||||
|
public static string DeclineAllRequests {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DeclineAllRequests", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Default.
|
/// Looks up a localized string similar to Default.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2029,6 +2065,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to DuckDuckGo.
|
||||||
|
/// </summary>
|
||||||
|
public static string DuckDuckGo {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DuckDuckGo", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Edit.
|
/// Looks up a localized string similar to Edit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2128,6 +2173,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Enable camera permission to use the scanner.
|
||||||
|
/// </summary>
|
||||||
|
public static string EnableCamerPermissionToUseTheScanner {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("EnableCamerPermissionToUseTheScanner", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Enabled.
|
/// Looks up a localized string similar to Enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2398,6 +2452,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Exposed Master Password.
|
||||||
|
/// </summary>
|
||||||
|
public static string ExposedMasterPassword {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ExposedMasterPassword", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Extension activated!.
|
/// Looks up a localized string similar to Extension activated!.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2506,6 +2569,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Fastmail.
|
||||||
|
/// </summary>
|
||||||
|
public static string Fastmail {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Fastmail", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Favorite.
|
/// Looks up a localized string similar to Favorite.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2920,6 +2992,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Good.
|
||||||
|
/// </summary>
|
||||||
|
public static string Good {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Good", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Go to my vault.
|
/// Looks up a localized string similar to Go to my vault.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3055,6 +3136,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Important.
|
||||||
|
/// </summary>
|
||||||
|
public static string Important {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Important", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Import items.
|
/// Looks up a localized string similar to Import items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3544,7 +3634,7 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Enterprise Single Sign-On.
|
/// Looks up a localized string similar to Enterprise single sign-on.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string LogInSso {
|
public static string LogInSso {
|
||||||
get {
|
get {
|
||||||
@@ -3589,7 +3679,7 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Log In with master password.
|
/// Looks up a localized string similar to Log in with master password.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string LogInWithMasterPassword {
|
public static string LogInWithMasterPassword {
|
||||||
get {
|
get {
|
||||||
@@ -3929,7 +4019,18 @@ namespace Bit.App.Resources {
|
|||||||
return ResourceManager.GetString("Ms", resourceCulture);
|
return ResourceManager.GetString("Ms", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Mx.
|
||||||
|
/// </summary>
|
||||||
|
public static string Mx
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ResourceManager.GetString("Mx", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to You must log into the main Bitwarden app before you can use the extension..
|
/// Looks up a localized string similar to You must log into the main Bitwarden app before you can use the extension..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -4200,6 +4301,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to No pending requests.
|
||||||
|
/// </summary>
|
||||||
|
public static string NoPendingRequests {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("NoPendingRequests", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Nord.
|
/// Looks up a localized string similar to Nord.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -4552,6 +4662,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?.
|
||||||
|
/// </summary>
|
||||||
|
public static string PasswordFoundInADataBreachAlertDescription {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("PasswordFoundInADataBreachAlertDescription", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Password generated.
|
/// Looks up a localized string similar to Password generated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -4678,6 +4797,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Pending login requests.
|
||||||
|
/// </summary>
|
||||||
|
public static string PendingLogInRequests {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("PendingLogInRequests", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to An organization policy is affecting your ownership options..
|
/// Looks up a localized string similar to An organization policy is affecting your ownership options..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -5030,6 +5158,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Requests declined.
|
||||||
|
/// </summary>
|
||||||
|
public static string RequestsDeclined {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("RequestsDeclined", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Resend code.
|
/// Looks up a localized string similar to Resend code.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -5237,15 +5374,6 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Looks up a localized string similar to .
|
|
||||||
/// </summary>
|
|
||||||
public static string SelectAddTotpToStoreTheKeySafely {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("SelectAddTotpToStoreTheKeySafely", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to You must select at least one collection..
|
/// Looks up a localized string similar to You must select at least one collection..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -5660,6 +5788,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Strong.
|
||||||
|
/// </summary>
|
||||||
|
public static string Strong {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Strong", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Submit.
|
/// Looks up a localized string similar to Submit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -6641,6 +6778,51 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Weak.
|
||||||
|
/// </summary>
|
||||||
|
public static string Weak {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Weak", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Weak and Exposed Master Password.
|
||||||
|
/// </summary>
|
||||||
|
public static string WeakAndExposedMasterPassword {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("WeakAndExposedMasterPassword", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Weak Master Password.
|
||||||
|
/// </summary>
|
||||||
|
public static string WeakMasterPassword {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("WeakMasterPassword", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?.
|
||||||
|
/// </summary>
|
||||||
|
public static string WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password?.
|
||||||
|
/// </summary>
|
||||||
|
public static string WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Website.
|
/// Looks up a localized string similar to Website.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -6758,6 +6940,15 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Your master password cannot be recovered if you forget it! {0} characters minimum..
|
||||||
|
/// </summary>
|
||||||
|
public static string YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to To continue, hold your YubiKey NEO against the back of the device or insert your YubiKey into your device's USB port, then touch its button..
|
/// Looks up a localized string similar to To continue, hold your YubiKey NEO against the back of the device or insert your YubiKey into your device's USB port, then touch its button..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -376,7 +376,7 @@
|
|||||||
</data>
|
</data>
|
||||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||||
<value>{0} is gekopieer.</value>
|
<value>{0} is gekopieer.</value>
|
||||||
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment>
|
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerifyFingerprint" xml:space="preserve">
|
<data name="VerifyFingerprint" xml:space="preserve">
|
||||||
<value>Bevestig vingerafdruk</value>
|
<value>Bevestig vingerafdruk</value>
|
||||||
@@ -1103,6 +1103,9 @@ Skandering gebeur outomaties.</value>
|
|||||||
<data name="Ms" xml:space="preserve">
|
<data name="Ms" xml:space="preserve">
|
||||||
<value>Mej.</value>
|
<value>Mej.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Mx" xml:space="preserve">
|
||||||
|
<value>Mx</value>
|
||||||
|
</data>
|
||||||
<data name="November" xml:space="preserve">
|
<data name="November" xml:space="preserve">
|
||||||
<value>November</value>
|
<value>November</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1576,7 +1579,7 @@ Skandering gebeur outomaties.</value>
|
|||||||
<comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment>
|
<comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="SolarizedDark" xml:space="preserve">
|
<data name="SolarizedDark" xml:space="preserve">
|
||||||
<value>Solarized Dark</value>
|
<value>'Solarized' Donker</value>
|
||||||
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
|
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillBlockedUris" xml:space="preserve">
|
<data name="AutofillBlockedUris" xml:space="preserve">
|
||||||
@@ -2299,9 +2302,6 @@ Skandering gebeur outomaties.</value>
|
|||||||
<value>Sodra u die sleutel reg ingevoer het,
|
<value>Sodra u die sleutel reg ingevoer het,
|
||||||
kies u Voeg TOTP toe om die sleutel veilig te bewaar</value>
|
kies u Voeg TOTP toe om die sleutel veilig te bewaar</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
|
|
||||||
<value></value>
|
|
||||||
</data>
|
|
||||||
<data name="NeverLockWarning" xml:space="preserve">
|
<data name="NeverLockWarning" xml:space="preserve">
|
||||||
<value>Deur u vergrendelopsies na “Nooit” te stel, is u kluis beskikbaar aan enigeen met toegang tot u toestel. Indien u hierdie opsie gebruik moet u seker maak dat u u toestel voldoende beskerm.</value>
|
<value>Deur u vergrendelopsies na “Nooit” te stel, is u kluis beskikbaar aan enigeen met toegang tot u toestel. Indien u hierdie opsie gebruik moet u seker maak dat u u toestel voldoende beskerm.</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2422,6 +2422,14 @@ kies u Voeg TOTP toe om die sleutel veilig te bewaar</value>
|
|||||||
<value>SimpleLogin</value>
|
<value>SimpleLogin</value>
|
||||||
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DuckDuckGo" xml:space="preserve">
|
||||||
|
<value>DuckDuckGo</value>
|
||||||
|
<comment>"DuckDuckGo" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Fastmail" xml:space="preserve">
|
||||||
|
<value>Fastmail</value>
|
||||||
|
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="APIAccessToken" xml:space="preserve">
|
<data name="APIAccessToken" xml:space="preserve">
|
||||||
<value>API-toegangsteken</value>
|
<value>API-toegangsteken</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2452,6 +2460,9 @@ kies u Voeg TOTP toe om die sleutel veilig te bewaar</value>
|
|||||||
<data name="Random" xml:space="preserve">
|
<data name="Random" xml:space="preserve">
|
||||||
<value>Lukraak</value>
|
<value>Lukraak</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectToWatch" xml:space="preserve">
|
||||||
|
<value>Koppel aan horlosie</value>
|
||||||
|
</data>
|
||||||
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
||||||
<value>Toeganklikheidsdiensopenbaarmaking</value>
|
<value>Toeganklikheidsdiensopenbaarmaking</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2468,47 +2479,101 @@ kies u Voeg TOTP toe om die sleutel veilig te bewaar</value>
|
|||||||
<value>Aantekenversoek het reeds verstryk.</value>
|
<value>Aantekenversoek het reeds verstryk.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve">
|
<data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve">
|
||||||
<value>Login attempt from:
|
<value>Teken Aan probeerslag van:
|
||||||
{0}
|
{0}
|
||||||
Do you want to switch to this account?</value>
|
Wil u na die rekening omskakel?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NewAroundHere" xml:space="preserve">
|
<data name="NewAroundHere" xml:space="preserve">
|
||||||
<value>New around here?</value>
|
<value>Nuut hier?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GetMasterPasswordwordHint" xml:space="preserve">
|
<data name="GetMasterPasswordwordHint" xml:space="preserve">
|
||||||
<value>Get master password hint</value>
|
<value>Kry hoofwagwoord wenk</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LoggingInAsX" xml:space="preserve">
|
<data name="LoggingInAsX" xml:space="preserve">
|
||||||
<value>Logging in as {0}</value>
|
<value>Teken in as {0}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NotYou" xml:space="preserve">
|
<data name="NotYou" xml:space="preserve">
|
||||||
<value>Not you?</value>
|
<value>Nie jy nie?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInWithMasterPassword" xml:space="preserve">
|
<data name="LogInWithMasterPassword" xml:space="preserve">
|
||||||
<value>Log in with master password</value>
|
<value>Teken aan met hoofwagwoord</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInWithAnotherDevice" xml:space="preserve">
|
<data name="LogInWithAnotherDevice" xml:space="preserve">
|
||||||
<value>Log In with another device</value>
|
<value>Teken Aan met 'n ander toestel</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInInitiated" xml:space="preserve">
|
<data name="LogInInitiated" xml:space="preserve">
|
||||||
<value>Log in initiated</value>
|
<value>Aanmelding begin</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
|
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
|
||||||
<value>A notification has been sent to your device.</value>
|
<value>'n Kennisgewing was gestuur na u toestel.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
|
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
|
||||||
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
|
<value>Asseblief maak seker jou kluis is oopgesluit en die vingerafdruk frase stem ooreen op die ander toestel.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ResendNotification" xml:space="preserve">
|
<data name="ResendNotification" xml:space="preserve">
|
||||||
<value>Resend notification</value>
|
<value>Stuur kennisgewing weer</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NeedAnotherOption" xml:space="preserve">
|
<data name="NeedAnotherOption" xml:space="preserve">
|
||||||
<value>Need another option?</value>
|
<value>Is daar nog 'n opsie nodig?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ViewAllLoginOptions" xml:space="preserve">
|
<data name="ViewAllLoginOptions" xml:space="preserve">
|
||||||
<value>View all log in options</value>
|
<value>Wys alle aanmeldings opsies</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
||||||
<value>This request is no longer valid</value>
|
<value>Hierdie versoek is nie langer gelding nie</value>
|
||||||
|
</data>
|
||||||
|
<data name="PendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Pending login requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeclineAllRequests" xml:space="preserve">
|
||||||
|
<value>Decline all requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Are you sure you want to decline all pending login requests?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequestsDeclined" xml:space="preserve">
|
||||||
|
<value>Requests declined</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoPendingRequests" xml:space="preserve">
|
||||||
|
<value>No pending requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
|
||||||
|
<value>Laat die kamera versoek toe om die skandeerder te gebruik</value>
|
||||||
|
</data>
|
||||||
|
<data name="Important" xml:space="preserve">
|
||||||
|
<value>Important</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
|
||||||
|
<value>Your master password cannot be recovered if you forget it! {0} characters minimum.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakMasterPassword" xml:space="preserve">
|
||||||
|
<value>Swak Hoofwagwoord</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
|
||||||
|
<value>Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Weak" xml:space="preserve">
|
||||||
|
<value>Swak</value>
|
||||||
|
</data>
|
||||||
|
<data name="Good" xml:space="preserve">
|
||||||
|
<value>Good</value>
|
||||||
|
</data>
|
||||||
|
<data name="Strong" xml:space="preserve">
|
||||||
|
<value>Strong</value>
|
||||||
|
</data>
|
||||||
|
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
|
||||||
|
<value>Check known data breaches for this password</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Weak and Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -118,17 +118,17 @@
|
|||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<data name="About" xml:space="preserve">
|
<data name="About" xml:space="preserve">
|
||||||
<value>حول</value>
|
<value>عن التطبيق</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Add" xml:space="preserve">
|
<data name="Add" xml:space="preserve">
|
||||||
<value>إضافة</value>
|
<value>أضِف</value>
|
||||||
<comment>Add/create a new entity (verb).</comment>
|
<comment>Add/create a new entity (verb).</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="AddFolder" xml:space="preserve">
|
<data name="AddFolder" xml:space="preserve">
|
||||||
<value>إضافة مجلد</value>
|
<value>مجلد مضاف</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AddItem" xml:space="preserve">
|
<data name="AddItem" xml:space="preserve">
|
||||||
<value>إضافة عنصر</value>
|
<value>تمت إضافة العنصر</value>
|
||||||
<comment>The title for the add item page.</comment>
|
<comment>The title for the add item page.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="AnErrorHasOccurred" xml:space="preserve">
|
<data name="AnErrorHasOccurred" xml:space="preserve">
|
||||||
@@ -323,14 +323,14 @@
|
|||||||
<comment>Label for a password.</comment>
|
<comment>Label for a password.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Save" xml:space="preserve">
|
<data name="Save" xml:space="preserve">
|
||||||
<value>تسجيل</value>
|
<value>حفظ</value>
|
||||||
<comment>Button text for a save operation (verb).</comment>
|
<comment>Button text for a save operation (verb).</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Move" xml:space="preserve">
|
<data name="Move" xml:space="preserve">
|
||||||
<value>نقل</value>
|
<value>نقل</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Saving" xml:space="preserve">
|
<data name="Saving" xml:space="preserve">
|
||||||
<value>تسجيل ...</value>
|
<value>حفظ...</value>
|
||||||
<comment>Message shown when interacting with the server</comment>
|
<comment>Message shown when interacting with the server</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Settings" xml:space="preserve">
|
<data name="Settings" xml:space="preserve">
|
||||||
@@ -376,7 +376,7 @@
|
|||||||
</data>
|
</data>
|
||||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||||
<value>{0} تم نسخه</value>
|
<value>{0} تم نسخه</value>
|
||||||
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment>
|
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerifyFingerprint" xml:space="preserve">
|
<data name="VerifyFingerprint" xml:space="preserve">
|
||||||
<value>التحقق من بصمة الإصبع</value>
|
<value>التحقق من بصمة الإصبع</value>
|
||||||
@@ -1103,6 +1103,9 @@
|
|||||||
<data name="Ms" xml:space="preserve">
|
<data name="Ms" xml:space="preserve">
|
||||||
<value>آنسة</value>
|
<value>آنسة</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Mx" xml:space="preserve">
|
||||||
|
<value>Mx</value>
|
||||||
|
</data>
|
||||||
<data name="November" xml:space="preserve">
|
<data name="November" xml:space="preserve">
|
||||||
<value>نوفمبر</value>
|
<value>نوفمبر</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2300,9 +2303,6 @@
|
|||||||
<value>بمجرد إدخال المفتاح بنجاح،
|
<value>بمجرد إدخال المفتاح بنجاح،
|
||||||
حدد إضافة TOTP لتخزين المفتاح بأمان</value>
|
حدد إضافة TOTP لتخزين المفتاح بأمان</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
|
|
||||||
<value></value>
|
|
||||||
</data>
|
|
||||||
<data name="NeverLockWarning" xml:space="preserve">
|
<data name="NeverLockWarning" xml:space="preserve">
|
||||||
<value>تعيين خيارات قفل الخاص بك إلى "مطلقا" يبقي خزنتك متاحةً لأي شخص لديه حق الوصول إلى جهازك. إذا كنت تستخدم هذا الخيار، يجب أن تتأكد من الحفاظ على حماية جهازك بشكل صحيح.</value>
|
<value>تعيين خيارات قفل الخاص بك إلى "مطلقا" يبقي خزنتك متاحةً لأي شخص لديه حق الوصول إلى جهازك. إذا كنت تستخدم هذا الخيار، يجب أن تتأكد من الحفاظ على حماية جهازك بشكل صحيح.</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2423,6 +2423,14 @@
|
|||||||
<value>SimpleLogin</value>
|
<value>SimpleLogin</value>
|
||||||
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DuckDuckGo" xml:space="preserve">
|
||||||
|
<value>DuckDuckGo</value>
|
||||||
|
<comment>"DuckDuckGo" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Fastmail" xml:space="preserve">
|
||||||
|
<value>Fastmail</value>
|
||||||
|
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="APIAccessToken" xml:space="preserve">
|
<data name="APIAccessToken" xml:space="preserve">
|
||||||
<value>رمز الوصول API</value>
|
<value>رمز الوصول API</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2453,6 +2461,9 @@
|
|||||||
<data name="Random" xml:space="preserve">
|
<data name="Random" xml:space="preserve">
|
||||||
<value>عشوائي</value>
|
<value>عشوائي</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectToWatch" xml:space="preserve">
|
||||||
|
<value>متّصل بالسّاعة</value>
|
||||||
|
</data>
|
||||||
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
||||||
<value>كشف خدمة إمكانية الوصول</value>
|
<value>كشف خدمة إمكانية الوصول</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2492,24 +2503,78 @@
|
|||||||
<value>تسجيل الدخول باستخدام جهاز آخر</value>
|
<value>تسجيل الدخول باستخدام جهاز آخر</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInInitiated" xml:space="preserve">
|
<data name="LogInInitiated" xml:space="preserve">
|
||||||
<value>Log in initiated</value>
|
<value>بدء تسجيل الدخول</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
|
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
|
||||||
<value>A notification has been sent to your device.</value>
|
<value>تم إرسال إشعار إلى جهازك.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
|
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
|
||||||
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
|
<value>الرجاء التأكد من أن الخزنة الخاصة بك غير مقفلة وأن عبارة بصمة الإصبع تتطابق على الجهاز الآخر.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ResendNotification" xml:space="preserve">
|
<data name="ResendNotification" xml:space="preserve">
|
||||||
<value>Resend notification</value>
|
<value>إعادة إرسال الإشعار</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NeedAnotherOption" xml:space="preserve">
|
<data name="NeedAnotherOption" xml:space="preserve">
|
||||||
<value>Need another option?</value>
|
<value>هل تحتاج إلى خيار آخر؟</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ViewAllLoginOptions" xml:space="preserve">
|
<data name="ViewAllLoginOptions" xml:space="preserve">
|
||||||
<value>View all log in options</value>
|
<value>عرض جميع خيارات تسجيل الدخول</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
||||||
<value>This request is no longer valid</value>
|
<value>هذا الطلب لم يعد صالحًا</value>
|
||||||
|
</data>
|
||||||
|
<data name="PendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Pending login requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeclineAllRequests" xml:space="preserve">
|
||||||
|
<value>Decline all requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Are you sure you want to decline all pending login requests?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequestsDeclined" xml:space="preserve">
|
||||||
|
<value>Requests declined</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoPendingRequests" xml:space="preserve">
|
||||||
|
<value>No pending requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
|
||||||
|
<value>تمكين إذن الكاميرا لاستخدام الماسح الضوئي</value>
|
||||||
|
</data>
|
||||||
|
<data name="Important" xml:space="preserve">
|
||||||
|
<value>Important</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
|
||||||
|
<value>Your master password cannot be recovered if you forget it! {0} characters minimum.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakMasterPassword" xml:space="preserve">
|
||||||
|
<value>Weak Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
|
||||||
|
<value>Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Weak" xml:space="preserve">
|
||||||
|
<value>Weak</value>
|
||||||
|
</data>
|
||||||
|
<data name="Good" xml:space="preserve">
|
||||||
|
<value>Good</value>
|
||||||
|
</data>
|
||||||
|
<data name="Strong" xml:space="preserve">
|
||||||
|
<value>Strong</value>
|
||||||
|
</data>
|
||||||
|
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
|
||||||
|
<value>Check known data breaches for this password</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Weak and Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -376,7 +376,7 @@
|
|||||||
</data>
|
</data>
|
||||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||||
<value>{0} kopyalandı.</value>
|
<value>{0} kopyalandı.</value>
|
||||||
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment>
|
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerifyFingerprint" xml:space="preserve">
|
<data name="VerifyFingerprint" xml:space="preserve">
|
||||||
<value>Barmaq izini təsdiqlə</value>
|
<value>Barmaq izini təsdiqlə</value>
|
||||||
@@ -1103,6 +1103,9 @@ Skan prosesi avtomatik baş tutacaq.</value>
|
|||||||
<data name="Ms" xml:space="preserve">
|
<data name="Ms" xml:space="preserve">
|
||||||
<value>Hörmətli</value>
|
<value>Hörmətli</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Mx" xml:space="preserve">
|
||||||
|
<value>Hörmətli</value>
|
||||||
|
</data>
|
||||||
<data name="November" xml:space="preserve">
|
<data name="November" xml:space="preserve">
|
||||||
<value>Noyabr</value>
|
<value>Noyabr</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2137,7 +2140,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
|
|||||||
<value>Bu təşkilat, sizi "parol sıfırlama"da avtomatik olaraq qeydiyyata alan müəssisə siyasətinə sahibdir. Qeydiyyat, təşkilat administratorlarına ana parolunuzu dəyişdirmə icazəsi verəcək.</value>
|
<value>Bu təşkilat, sizi "parol sıfırlama"da avtomatik olaraq qeydiyyata alan müəssisə siyasətinə sahibdir. Qeydiyyat, təşkilat administratorlarına ana parolunuzu dəyişdirmə icazəsi verəcək.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="VaultTimeoutPolicyInEffect" xml:space="preserve">
|
<data name="VaultTimeoutPolicyInEffect" xml:space="preserve">
|
||||||
<value>Təşkilatınızın siyasətləri, anbarınızın vaxt bitişinə təsir edir. Anbar vaxt bitişi üçün icazə verilən maksimum vaxt $HOURS$ saat $MINUTES$ dəqiqədir</value>
|
<value>Təşkilatınızın siyasətləri, anbarınızın vaxt bitişinə təsir edir. Anbar vaxt bitişi üçün icazə verilən maksimum vaxt {0} saat {1} dəqiqədir</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="VaultTimeoutToLarge" xml:space="preserve">
|
<data name="VaultTimeoutToLarge" xml:space="preserve">
|
||||||
<value>Anbar vaxt bitişi, təşkilatınız tərəfindən tənzimlənən məhdudiyyətləri aşır.</value>
|
<value>Anbar vaxt bitişi, təşkilatınız tərəfindən tənzimlənən məhdudiyyətləri aşır.</value>
|
||||||
@@ -2298,9 +2301,6 @@ Skan prosesi avtomatik baş tutacaq.</value>
|
|||||||
<data name="OnceTheKeyIsSuccessfullyEntered" xml:space="preserve">
|
<data name="OnceTheKeyIsSuccessfullyEntered" xml:space="preserve">
|
||||||
<value>Açar uğurla daxil edildikdən sonra, açarı güvənli şəkildə saxlamaq üçün "TOTP əlavə et"i seçin</value>
|
<value>Açar uğurla daxil edildikdən sonra, açarı güvənli şəkildə saxlamaq üçün "TOTP əlavə et"i seçin</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
|
|
||||||
<value></value>
|
|
||||||
</data>
|
|
||||||
<data name="NeverLockWarning" xml:space="preserve">
|
<data name="NeverLockWarning" xml:space="preserve">
|
||||||
<value>Kilid seçimlərini "Heç vaxt" olaraq tənzimləmək, anbarınızı cihazınıza müraciəti olan hər kəsə əlçatan edir. Bu seçimi istifadə etsəniz, cihazınızı düzgün qoruduğunuza əmin olmalısınız.</value>
|
<value>Kilid seçimlərini "Heç vaxt" olaraq tənzimləmək, anbarınızı cihazınıza müraciəti olan hər kəsə əlçatan edir. Bu seçimi istifadə etsəniz, cihazınızı düzgün qoruduğunuza əmin olmalısınız.</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2421,6 +2421,14 @@ Skan prosesi avtomatik baş tutacaq.</value>
|
|||||||
<value>SimpleLogin</value>
|
<value>SimpleLogin</value>
|
||||||
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DuckDuckGo" xml:space="preserve">
|
||||||
|
<value>DuckDuckGo</value>
|
||||||
|
<comment>"DuckDuckGo" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Fastmail" xml:space="preserve">
|
||||||
|
<value>Fastmail</value>
|
||||||
|
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="APIAccessToken" xml:space="preserve">
|
<data name="APIAccessToken" xml:space="preserve">
|
||||||
<value>API müraciət tokeni</value>
|
<value>API müraciət tokeni</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2451,6 +2459,9 @@ Skan prosesi avtomatik baş tutacaq.</value>
|
|||||||
<data name="Random" xml:space="preserve">
|
<data name="Random" xml:space="preserve">
|
||||||
<value>Təsadüfi</value>
|
<value>Təsadüfi</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectToWatch" xml:space="preserve">
|
||||||
|
<value>"Watch"a bağlan</value>
|
||||||
|
</data>
|
||||||
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
||||||
<value>Əlçatımlılıq Xidməti açıqlaması</value>
|
<value>Əlçatımlılıq Xidməti açıqlaması</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2510,4 +2521,58 @@ Bu hesaba keçmək istəyirsiniz?</value>
|
|||||||
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
||||||
<value>Bu tələb artıq yararsızdır</value>
|
<value>Bu tələb artıq yararsızdır</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Giriş tələbləri gözlənilir</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeclineAllRequests" xml:space="preserve">
|
||||||
|
<value>Bütün tələbləri rədd et</value>
|
||||||
|
</data>
|
||||||
|
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Gözləyən bütün giriş tələblərini rədd etmək istədiyinizə əminsiniz?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequestsDeclined" xml:space="preserve">
|
||||||
|
<value>Tələblər rədd edildi</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoPendingRequests" xml:space="preserve">
|
||||||
|
<value>Gözləyən heç bir tələb yoxdur</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
|
||||||
|
<value>Skaneri istifadə etmək üçün kamera icazəsini fəallaşdırın</value>
|
||||||
|
</data>
|
||||||
|
<data name="Important" xml:space="preserve">
|
||||||
|
<value>Vacib</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
|
||||||
|
<value>Ana parolunuzu unutsanız bərpa edə bilməzsiniz! Ən az {0} simvol.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakMasterPassword" xml:space="preserve">
|
||||||
|
<value>Zəif ana parol</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
|
||||||
|
<value>Zəif parol aşkarlandı. Hesabınızı qorumaq üçün güclü bir parol istifadə edin. Zəif bir parol istifadə etmək istədiyinizə əminsiniz?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Weak" xml:space="preserve">
|
||||||
|
<value>Zəif</value>
|
||||||
|
</data>
|
||||||
|
<data name="Good" xml:space="preserve">
|
||||||
|
<value>Yaxşı</value>
|
||||||
|
</data>
|
||||||
|
<data name="Strong" xml:space="preserve">
|
||||||
|
<value>Güclü</value>
|
||||||
|
</data>
|
||||||
|
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
|
||||||
|
<value>Bu parol üçün bilinən məlumat pozuntularını yoxlayın</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>İfşa olunmuş ana parol</value>
|
||||||
|
</data>
|
||||||
|
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Parol, məlumat pozuntusunda tapıldı. Hesabınızı qorumaq üçün unikal bir parol istifadə edin. İfşa olunmuş bir parol istifadə etmək istədiyinizə əminsiniz?</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Zəif və ifşa olunmuş ana parol</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Zəif parol məlumat pozuntusunda aşkarlandı və tapıldı. Hesabınızı qorumaq üçün güclü və unikal bir parol istifadə edin. Bu parolu istifadə etmək istədiyinizə əminsiniz?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -376,7 +376,7 @@
|
|||||||
</data>
|
</data>
|
||||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||||
<value>{0} скапіяваны</value>
|
<value>{0} скапіяваны</value>
|
||||||
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment>
|
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerifyFingerprint" xml:space="preserve">
|
<data name="VerifyFingerprint" xml:space="preserve">
|
||||||
<value>Праверка адбітка пальца</value>
|
<value>Праверка адбітка пальца</value>
|
||||||
@@ -1102,6 +1102,9 @@
|
|||||||
<data name="Ms" xml:space="preserve">
|
<data name="Ms" xml:space="preserve">
|
||||||
<value>Пані</value>
|
<value>Пані</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Mx" xml:space="preserve">
|
||||||
|
<value>Mx</value>
|
||||||
|
</data>
|
||||||
<data name="November" xml:space="preserve">
|
<data name="November" xml:space="preserve">
|
||||||
<value>Лістапад</value>
|
<value>Лістапад</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1575,7 +1578,7 @@
|
|||||||
<comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment>
|
<comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="SolarizedDark" xml:space="preserve">
|
<data name="SolarizedDark" xml:space="preserve">
|
||||||
<value>Цёмная Solarized</value>
|
<value>Solarized Dark</value>
|
||||||
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
|
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillBlockedUris" xml:space="preserve">
|
<data name="AutofillBlockedUris" xml:space="preserve">
|
||||||
@@ -2299,9 +2302,6 @@
|
|||||||
<value>Пасля таго, як ваш ключ паспяхова ўведзены,
|
<value>Пасля таго, як ваш ключ паспяхова ўведзены,
|
||||||
выберыце "Дадаць TOTP" для надзейнага захавання ключа</value>
|
выберыце "Дадаць TOTP" для надзейнага захавання ключа</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
|
|
||||||
<value></value>
|
|
||||||
</data>
|
|
||||||
<data name="NeverLockWarning" xml:space="preserve">
|
<data name="NeverLockWarning" xml:space="preserve">
|
||||||
<value>Прызначыўшы параметр блакіравання "Ніколі", ваша сховішча будзе даступна кожнаму, хто мае доступ да вашай прылады. Калі вы выкарыстоўваеце гэты параметр, вы павінны быць упэўнены ў тым, што ваша прылада надзейна абаронена.</value>
|
<value>Прызначыўшы параметр блакіравання "Ніколі", ваша сховішча будзе даступна кожнаму, хто мае доступ да вашай прылады. Калі вы выкарыстоўваеце гэты параметр, вы павінны быць упэўнены ў тым, што ваша прылада надзейна абаронена.</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2422,6 +2422,14 @@
|
|||||||
<value>SimpleLogin</value>
|
<value>SimpleLogin</value>
|
||||||
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DuckDuckGo" xml:space="preserve">
|
||||||
|
<value>DuckDuckGo</value>
|
||||||
|
<comment>"DuckDuckGo" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Fastmail" xml:space="preserve">
|
||||||
|
<value>Fastmail</value>
|
||||||
|
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="APIAccessToken" xml:space="preserve">
|
<data name="APIAccessToken" xml:space="preserve">
|
||||||
<value>Токен доступу да API</value>
|
<value>Токен доступу да API</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2452,6 +2460,9 @@
|
|||||||
<data name="Random" xml:space="preserve">
|
<data name="Random" xml:space="preserve">
|
||||||
<value>Выпадкова</value>
|
<value>Выпадкова</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectToWatch" xml:space="preserve">
|
||||||
|
<value>Падлучыцца да гадзінніка</value>
|
||||||
|
</data>
|
||||||
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
||||||
<value>Апісанне службы спецыяльных магчымасцей</value>
|
<value>Апісанне службы спецыяльных магчымасцей</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2511,4 +2522,58 @@
|
|||||||
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
||||||
<value>Гэты запыт больш не дзейнічае</value>
|
<value>Гэты запыт больш не дзейнічае</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Чаканне запыту на ўваход</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeclineAllRequests" xml:space="preserve">
|
||||||
|
<value>Адхіліць усе запыты</value>
|
||||||
|
</data>
|
||||||
|
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Вы сапраўды хочаце адхіліць усе запыты, якія чакаюць уваходу?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequestsDeclined" xml:space="preserve">
|
||||||
|
<value>Запыты адхілены</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoPendingRequests" xml:space="preserve">
|
||||||
|
<value>Няма запытаў, якія чакаюць уваходу</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
|
||||||
|
<value>Каб выкарыстоўваць сканер дайце дазвол на выкарыстанне камеры</value>
|
||||||
|
</data>
|
||||||
|
<data name="Important" xml:space="preserve">
|
||||||
|
<value>Важна</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
|
||||||
|
<value>Ваш асноўны пароль нельга будзе аднавіць, калі вы забудзеце яго! Мінімальная колькасць сімвалаў: {0}.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakMasterPassword" xml:space="preserve">
|
||||||
|
<value>Ненадзейны асноўны пароль</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
|
||||||
|
<value>Вызначаны ненадзейны пароль. Выкарыстоўвайце надзейны пароль для абароны вашага ўліковага запісу. Вы сапраўды хочаце выкарыстоўваць ненадзейны пароль?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Weak" xml:space="preserve">
|
||||||
|
<value>Ненадзейны</value>
|
||||||
|
</data>
|
||||||
|
<data name="Good" xml:space="preserve">
|
||||||
|
<value>Добры</value>
|
||||||
|
</data>
|
||||||
|
<data name="Strong" xml:space="preserve">
|
||||||
|
<value>Надзейны</value>
|
||||||
|
</data>
|
||||||
|
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
|
||||||
|
<value>Праверыць у вядомых уцечках даных для гэтага пароля</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Скампраметаваны асноўны пароль</value>
|
||||||
|
</data>
|
||||||
|
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Пароль знойдзены ва ўцечках даных. Выкарыстоўвайце ўнікальныя паролі для абароны свайго ўліковага запісу. Вы сапраўды хочаце выкарыстоўваць скампраметаваны пароль?</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Ненадзейны і скампраметаваны асноўны пароль</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Вызначаны ненадзейны пароль, які знойдзены ва ўцечках даных. Выкарыстоўвайце надзейныя і ўнікальныя паролі для абароны свайго ўліковага запісу. Вы сапраўды хочаце выкарыстоўваць гэты пароль?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -300,7 +300,7 @@
|
|||||||
<comment>The title for the vault page.</comment>
|
<comment>The title for the vault page.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Authenticator" xml:space="preserve">
|
<data name="Authenticator" xml:space="preserve">
|
||||||
<value>Authenticator</value>
|
<value>Удостоверител</value>
|
||||||
<comment>Authenticator TOTP feature</comment>
|
<comment>Authenticator TOTP feature</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Name" xml:space="preserve">
|
<data name="Name" xml:space="preserve">
|
||||||
@@ -376,7 +376,7 @@
|
|||||||
</data>
|
</data>
|
||||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||||
<value>{0} беше копирано.</value>
|
<value>{0} беше копирано.</value>
|
||||||
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment>
|
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerifyFingerprint" xml:space="preserve">
|
<data name="VerifyFingerprint" xml:space="preserve">
|
||||||
<value>Потвърждаване на пръстовия отпечатък</value>
|
<value>Потвърждаване на пръстовия отпечатък</value>
|
||||||
@@ -1103,6 +1103,9 @@
|
|||||||
<data name="Ms" xml:space="preserve">
|
<data name="Ms" xml:space="preserve">
|
||||||
<value>Г-ца</value>
|
<value>Г-ца</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Mx" xml:space="preserve">
|
||||||
|
<value>Mx</value>
|
||||||
|
</data>
|
||||||
<data name="November" xml:space="preserve">
|
<data name="November" xml:space="preserve">
|
||||||
<value>ноември</value>
|
<value>ноември</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2080,7 +2083,7 @@
|
|||||||
<value>Това действие е защитено. За да продължите, въведете отново главната си парола, за да потвърдите самоличността си.</value>
|
<value>Това действие е защитено. За да продължите, въведете отново главната си парола, за да потвърдите самоличността си.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CaptchaRequired" xml:space="preserve">
|
<data name="CaptchaRequired" xml:space="preserve">
|
||||||
<value>Captcha required</value>
|
<value>Адресът за hCaptcha е задължителен</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CaptchaFailed" xml:space="preserve">
|
<data name="CaptchaFailed" xml:space="preserve">
|
||||||
<value>
|
<value>
|
||||||
@@ -2267,7 +2270,7 @@
|
|||||||
<value>Всички</value>
|
<value>Всички</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Totp" xml:space="preserve">
|
<data name="Totp" xml:space="preserve">
|
||||||
<value>TOTP</value>
|
<value>Кода за потвърждаване</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerificationCodes" xml:space="preserve">
|
<data name="VerificationCodes" xml:space="preserve">
|
||||||
<value>Кодове за потвърждаване</value>
|
<value>Кодове за потвърждаване</value>
|
||||||
@@ -2291,18 +2294,15 @@
|
|||||||
<value>Ръчно въвеждане на кода</value>
|
<value>Ръчно въвеждане на кода</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AddTotp" xml:space="preserve">
|
<data name="AddTotp" xml:space="preserve">
|
||||||
<value>Add TOTP</value>
|
<value>Копиране на кода за потвърждаване</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SetupTotp" xml:space="preserve">
|
<data name="SetupTotp" xml:space="preserve">
|
||||||
<value>Set up TOTP</value>
|
<value>Копиране на кода за потвърждаване</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OnceTheKeyIsSuccessfullyEntered" xml:space="preserve">
|
<data name="OnceTheKeyIsSuccessfullyEntered" xml:space="preserve">
|
||||||
<value>Once the key is successfully entered,
|
<value>Once the key is successfully entered,
|
||||||
select Add TOTP to store the key safely</value>
|
select Add TOTP to store the key safely</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
|
|
||||||
<value></value>
|
|
||||||
</data>
|
|
||||||
<data name="NeverLockWarning" xml:space="preserve">
|
<data name="NeverLockWarning" xml:space="preserve">
|
||||||
<value>Ако изберете „Никога“ като настройка за заключването, трезорът Ви ще бъде достъпен за всеки, който има досег с устройството. Ако използвате тази настройка, трябва да се уверите, че устройството Ви е удачно защитено.</value>
|
<value>Ако изберете „Никога“ като настройка за заключването, трезорът Ви ще бъде достъпен за всеки, който има досег с устройството. Ако използвате тази настройка, трябва да се уверите, че устройството Ви е удачно защитено.</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2337,7 +2337,7 @@ select Add TOTP to store the key safely</value>
|
|||||||
<value>Време</value>
|
<value>Време</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Near" xml:space="preserve">
|
<data name="Near" xml:space="preserve">
|
||||||
<value>Near</value>
|
<value>Близо</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ConfirmLogIn" xml:space="preserve">
|
<data name="ConfirmLogIn" xml:space="preserve">
|
||||||
<value>Потвърждаване на вписването</value>
|
<value>Потвърждаване на вписването</value>
|
||||||
@@ -2388,13 +2388,13 @@ select Add TOTP to store the key safely</value>
|
|||||||
<value>Тип потребителско име</value>
|
<value>Тип потребителско име</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PlusAddressedEmail" xml:space="preserve">
|
<data name="PlusAddressedEmail" xml:space="preserve">
|
||||||
<value>Plus addressed email</value>
|
<value>Адрес на е-поща с плюс</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CatchAllEmail" xml:space="preserve">
|
<data name="CatchAllEmail" xml:space="preserve">
|
||||||
<value>Catch-all email</value>
|
<value>Хващаща всичко е-поща</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ForwardedEmailAlias" xml:space="preserve">
|
<data name="ForwardedEmailAlias" xml:space="preserve">
|
||||||
<value>Forwarded email alias</value>
|
<value>Псевдоним на препратена е-поща</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RandomWord" xml:space="preserve">
|
<data name="RandomWord" xml:space="preserve">
|
||||||
<value>Произволна дума</value>
|
<value>Произволна дума</value>
|
||||||
@@ -2423,6 +2423,14 @@ select Add TOTP to store the key safely</value>
|
|||||||
<value>SimpleLogin</value>
|
<value>SimpleLogin</value>
|
||||||
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DuckDuckGo" xml:space="preserve">
|
||||||
|
<value>DuckDuckGo</value>
|
||||||
|
<comment>"DuckDuckGo" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Fastmail" xml:space="preserve">
|
||||||
|
<value>Fastmail</value>
|
||||||
|
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="APIAccessToken" xml:space="preserve">
|
<data name="APIAccessToken" xml:space="preserve">
|
||||||
<value>Идентификатор за достъп до API</value>
|
<value>Идентификатор за достъп до API</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2433,7 +2441,7 @@ select Add TOTP to store the key safely</value>
|
|||||||
<value>Генериране на потр. име</value>
|
<value>Генериране на потр. име</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EmailType" xml:space="preserve">
|
<data name="EmailType" xml:space="preserve">
|
||||||
<value>Email Type</value>
|
<value>Вид е-поща</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="WebsiteRequired" xml:space="preserve">
|
<data name="WebsiteRequired" xml:space="preserve">
|
||||||
<value>Уеб сайт (задължително)</value>
|
<value>Уеб сайт (задължително)</value>
|
||||||
@@ -2445,14 +2453,17 @@ select Add TOTP to store the key safely</value>
|
|||||||
<value>Използвайте възможностите за под-адресиране на е-поща на своя доставчик</value>
|
<value>Използвайте възможностите за под-адресиране на е-поща на своя доставчик</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CatchAllEmailDescription" xml:space="preserve">
|
<data name="CatchAllEmailDescription" xml:space="preserve">
|
||||||
<value>Use your domain's configured catch-all inbox.</value>
|
<value>Използвайте конфигурираната входяща кутия за събиране на всичко.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ForwardedEmailDescription" xml:space="preserve">
|
<data name="ForwardedEmailDescription" xml:space="preserve">
|
||||||
<value>Generate an email alias with an external forwarding service.</value>
|
<value>Създайте псевдоним на е-поща с външна услуга за препращане.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Random" xml:space="preserve">
|
<data name="Random" xml:space="preserve">
|
||||||
<value>Произволно</value>
|
<value>Произволно</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectToWatch" xml:space="preserve">
|
||||||
|
<value>Свързване към часовник</value>
|
||||||
|
</data>
|
||||||
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
||||||
<value>Използване на услугата за достъпност</value>
|
<value>Използване на услугата за достъпност</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2512,4 +2523,58 @@ select Add TOTP to store the key safely</value>
|
|||||||
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
||||||
<value>Тази зявка вече не е приложима</value>
|
<value>Тази зявка вече не е приложима</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Чакащи заявки за вписване</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeclineAllRequests" xml:space="preserve">
|
||||||
|
<value>Отказване на всички заявки</value>
|
||||||
|
</data>
|
||||||
|
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Наистина ли искате да откажете всички чакащи заявки за вписване?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequestsDeclined" xml:space="preserve">
|
||||||
|
<value>Заявките са отказани</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoPendingRequests" xml:space="preserve">
|
||||||
|
<value>Няма чакащи заявки</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
|
||||||
|
<value>Разрешете достъпа до камерата, за да използвате скенера</value>
|
||||||
|
</data>
|
||||||
|
<data name="Important" xml:space="preserve">
|
||||||
|
<value>Важно</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
|
||||||
|
<value>Главната парола не може да бъде възстановена, ако я забравите! Дължината трябва да е поне {0} знака.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakMasterPassword" xml:space="preserve">
|
||||||
|
<value>Слаба главна парола</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
|
||||||
|
<value>Разпозната е слаба парола. Използвайте силна парола, за да защитете данните си. Наистина ли искате да използвате слаба парола?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Weak" xml:space="preserve">
|
||||||
|
<value>Слаба</value>
|
||||||
|
</data>
|
||||||
|
<data name="Good" xml:space="preserve">
|
||||||
|
<value>Добра</value>
|
||||||
|
</data>
|
||||||
|
<data name="Strong" xml:space="preserve">
|
||||||
|
<value>Силна</value>
|
||||||
|
</data>
|
||||||
|
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
|
||||||
|
<value>Проверяване в известните случаи на изтекли данни за тази парола</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Weak and Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -376,7 +376,7 @@
|
|||||||
</data>
|
</data>
|
||||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||||
<value>{0} copied</value>
|
<value>{0} copied</value>
|
||||||
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment>
|
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerifyFingerprint" xml:space="preserve">
|
<data name="VerifyFingerprint" xml:space="preserve">
|
||||||
<value>Verify fingerprint</value>
|
<value>Verify fingerprint</value>
|
||||||
@@ -1103,6 +1103,9 @@ Scanning will happen automatically.</value>
|
|||||||
<data name="Ms" xml:space="preserve">
|
<data name="Ms" xml:space="preserve">
|
||||||
<value>Ms</value>
|
<value>Ms</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Mx" xml:space="preserve">
|
||||||
|
<value>Mx</value>
|
||||||
|
</data>
|
||||||
<data name="November" xml:space="preserve">
|
<data name="November" xml:space="preserve">
|
||||||
<value>November</value>
|
<value>November</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2300,9 +2303,6 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Once the key is successfully entered,
|
<value>Once the key is successfully entered,
|
||||||
select Add TOTP to store the key safely</value>
|
select Add TOTP to store the key safely</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
|
|
||||||
<value></value>
|
|
||||||
</data>
|
|
||||||
<data name="NeverLockWarning" xml:space="preserve">
|
<data name="NeverLockWarning" xml:space="preserve">
|
||||||
<value>Setting your lock options to “Never” keeps your vault available to anyone with access to your device. If you use this option, you should ensure that you keep your device properly protected.</value>
|
<value>Setting your lock options to “Never” keeps your vault available to anyone with access to your device. If you use this option, you should ensure that you keep your device properly protected.</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2423,6 +2423,14 @@ select Add TOTP to store the key safely</value>
|
|||||||
<value>SimpleLogin</value>
|
<value>SimpleLogin</value>
|
||||||
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DuckDuckGo" xml:space="preserve">
|
||||||
|
<value>DuckDuckGo</value>
|
||||||
|
<comment>"DuckDuckGo" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Fastmail" xml:space="preserve">
|
||||||
|
<value>Fastmail</value>
|
||||||
|
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="APIAccessToken" xml:space="preserve">
|
<data name="APIAccessToken" xml:space="preserve">
|
||||||
<value>API access token</value>
|
<value>API access token</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2453,6 +2461,9 @@ select Add TOTP to store the key safely</value>
|
|||||||
<data name="Random" xml:space="preserve">
|
<data name="Random" xml:space="preserve">
|
||||||
<value>Random</value>
|
<value>Random</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectToWatch" xml:space="preserve">
|
||||||
|
<value>Connect to Watch</value>
|
||||||
|
</data>
|
||||||
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
||||||
<value>Accessibility Service Disclosure</value>
|
<value>Accessibility Service Disclosure</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2489,7 +2500,7 @@ Do you want to switch to this account?</value>
|
|||||||
<value>Log in with master password</value>
|
<value>Log in with master password</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInWithAnotherDevice" xml:space="preserve">
|
<data name="LogInWithAnotherDevice" xml:space="preserve">
|
||||||
<value>Log In with another device</value>
|
<value>Log in with device</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInInitiated" xml:space="preserve">
|
<data name="LogInInitiated" xml:space="preserve">
|
||||||
<value>Log in initiated</value>
|
<value>Log in initiated</value>
|
||||||
@@ -2512,4 +2523,58 @@ Do you want to switch to this account?</value>
|
|||||||
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
||||||
<value>This request is no longer valid</value>
|
<value>This request is no longer valid</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Pending login requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeclineAllRequests" xml:space="preserve">
|
||||||
|
<value>Decline all requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Are you sure you want to decline all pending login requests?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequestsDeclined" xml:space="preserve">
|
||||||
|
<value>Requests declined</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoPendingRequests" xml:space="preserve">
|
||||||
|
<value>No pending requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
|
||||||
|
<value>Enable camera permission to use the scanner</value>
|
||||||
|
</data>
|
||||||
|
<data name="Important" xml:space="preserve">
|
||||||
|
<value>Important</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
|
||||||
|
<value>Your master password cannot be recovered if you forget it! {0} characters minimum.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakMasterPassword" xml:space="preserve">
|
||||||
|
<value>Weak Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
|
||||||
|
<value>Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Weak" xml:space="preserve">
|
||||||
|
<value>Weak</value>
|
||||||
|
</data>
|
||||||
|
<data name="Good" xml:space="preserve">
|
||||||
|
<value>Good</value>
|
||||||
|
</data>
|
||||||
|
<data name="Strong" xml:space="preserve">
|
||||||
|
<value>Strong</value>
|
||||||
|
</data>
|
||||||
|
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
|
||||||
|
<value>Check known data breaches for this password</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Weak and Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -376,7 +376,7 @@
|
|||||||
</data>
|
</data>
|
||||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||||
<value>{0} kopirano.</value>
|
<value>{0} kopirano.</value>
|
||||||
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment>
|
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerifyFingerprint" xml:space="preserve">
|
<data name="VerifyFingerprint" xml:space="preserve">
|
||||||
<value>Potvrdi otisak prsta</value>
|
<value>Potvrdi otisak prsta</value>
|
||||||
@@ -1103,6 +1103,9 @@ Scanning will happen automatically.</value>
|
|||||||
<data name="Ms" xml:space="preserve">
|
<data name="Ms" xml:space="preserve">
|
||||||
<value>Gđica</value>
|
<value>Gđica</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Mx" xml:space="preserve">
|
||||||
|
<value>Mx</value>
|
||||||
|
</data>
|
||||||
<data name="November" xml:space="preserve">
|
<data name="November" xml:space="preserve">
|
||||||
<value>Novembar</value>
|
<value>Novembar</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1412,7 +1415,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Nema kolekcija za prikazati.</value>
|
<value>Nema kolekcija za prikazati.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MovedItemToOrg" xml:space="preserve">
|
<data name="MovedItemToOrg" xml:space="preserve">
|
||||||
<value>premješteno u</value>
|
<value>{0} moved to {1}.</value>
|
||||||
<comment>ex: Item moved to Organization.</comment>
|
<comment>ex: Item moved to Organization.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ItemShared" xml:space="preserve">
|
<data name="ItemShared" xml:space="preserve">
|
||||||
@@ -2299,9 +2302,6 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Once the key is successfully entered,
|
<value>Once the key is successfully entered,
|
||||||
select Add TOTP to store the key safely</value>
|
select Add TOTP to store the key safely</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
|
|
||||||
<value></value>
|
|
||||||
</data>
|
|
||||||
<data name="NeverLockWarning" xml:space="preserve">
|
<data name="NeverLockWarning" xml:space="preserve">
|
||||||
<value>Setting your lock options to “Never” keeps your vault available to anyone with access to your device. If you use this option, you should ensure that you keep your device properly protected.</value>
|
<value>Setting your lock options to “Never” keeps your vault available to anyone with access to your device. If you use this option, you should ensure that you keep your device properly protected.</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2422,6 +2422,14 @@ select Add TOTP to store the key safely</value>
|
|||||||
<value>SimpleLogin</value>
|
<value>SimpleLogin</value>
|
||||||
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DuckDuckGo" xml:space="preserve">
|
||||||
|
<value>DuckDuckGo</value>
|
||||||
|
<comment>"DuckDuckGo" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Fastmail" xml:space="preserve">
|
||||||
|
<value>Fastmail</value>
|
||||||
|
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="APIAccessToken" xml:space="preserve">
|
<data name="APIAccessToken" xml:space="preserve">
|
||||||
<value>API access token</value>
|
<value>API access token</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2452,6 +2460,9 @@ select Add TOTP to store the key safely</value>
|
|||||||
<data name="Random" xml:space="preserve">
|
<data name="Random" xml:space="preserve">
|
||||||
<value>Random</value>
|
<value>Random</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectToWatch" xml:space="preserve">
|
||||||
|
<value>Connect to Watch</value>
|
||||||
|
</data>
|
||||||
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
||||||
<value>Accessibility Service Disclosure</value>
|
<value>Accessibility Service Disclosure</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2488,7 +2499,7 @@ Do you want to switch to this account?</value>
|
|||||||
<value>Log in with master password</value>
|
<value>Log in with master password</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInWithAnotherDevice" xml:space="preserve">
|
<data name="LogInWithAnotherDevice" xml:space="preserve">
|
||||||
<value>Log In with another device</value>
|
<value>Log in with device</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInInitiated" xml:space="preserve">
|
<data name="LogInInitiated" xml:space="preserve">
|
||||||
<value>Log in initiated</value>
|
<value>Log in initiated</value>
|
||||||
@@ -2511,4 +2522,58 @@ Do you want to switch to this account?</value>
|
|||||||
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
||||||
<value>This request is no longer valid</value>
|
<value>This request is no longer valid</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Pending login requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeclineAllRequests" xml:space="preserve">
|
||||||
|
<value>Decline all requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Are you sure you want to decline all pending login requests?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequestsDeclined" xml:space="preserve">
|
||||||
|
<value>Requests declined</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoPendingRequests" xml:space="preserve">
|
||||||
|
<value>No pending requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
|
||||||
|
<value>Enable camera permission to use the scanner</value>
|
||||||
|
</data>
|
||||||
|
<data name="Important" xml:space="preserve">
|
||||||
|
<value>Important</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
|
||||||
|
<value>Your master password cannot be recovered if you forget it! {0} characters minimum.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakMasterPassword" xml:space="preserve">
|
||||||
|
<value>Weak Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
|
||||||
|
<value>Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Weak" xml:space="preserve">
|
||||||
|
<value>Weak</value>
|
||||||
|
</data>
|
||||||
|
<data name="Good" xml:space="preserve">
|
||||||
|
<value>Good</value>
|
||||||
|
</data>
|
||||||
|
<data name="Strong" xml:space="preserve">
|
||||||
|
<value>Strong</value>
|
||||||
|
</data>
|
||||||
|
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
|
||||||
|
<value>Check known data breaches for this password</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Weak and Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -376,7 +376,7 @@
|
|||||||
</data>
|
</data>
|
||||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||||
<value>S'ha copiat '{0}'.</value>
|
<value>S'ha copiat '{0}'.</value>
|
||||||
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment>
|
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerifyFingerprint" xml:space="preserve">
|
<data name="VerifyFingerprint" xml:space="preserve">
|
||||||
<value>Verifica empremta digital</value>
|
<value>Verifica empremta digital</value>
|
||||||
@@ -556,7 +556,7 @@
|
|||||||
<value>Temps d'espera de la caixa forta</value>
|
<value>Temps d'espera de la caixa forta</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="VaultTimeoutAction" xml:space="preserve">
|
<data name="VaultTimeoutAction" xml:space="preserve">
|
||||||
<value>Acció del temps d'espera de la caixa forta</value>
|
<value>Acció quan acabe el temps d'espera de la caixa forta</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="VaultTimeoutLogOutConfirmation" xml:space="preserve">
|
<data name="VaultTimeoutLogOutConfirmation" xml:space="preserve">
|
||||||
<value>En tancar la sessió s'eliminarà tot l'accés a la vostra caixa forta i es requerirà una autenticació en línia després del període de temps d'espera. Esteu segur que voleu utilitzar aquesta configuració?</value>
|
<value>En tancar la sessió s'eliminarà tot l'accés a la vostra caixa forta i es requerirà una autenticació en línia després del període de temps d'espera. Esteu segur que voleu utilitzar aquesta configuració?</value>
|
||||||
@@ -769,16 +769,16 @@
|
|||||||
<value>2. Activeu el commutador i premeu d'acord per acceptar.</value>
|
<value>2. Activeu el commutador i premeu d'acord per acceptar.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Disabled" xml:space="preserve">
|
<data name="Disabled" xml:space="preserve">
|
||||||
<value>Deshabilitat</value>
|
<value>No</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Enabled" xml:space="preserve">
|
<data name="Enabled" xml:space="preserve">
|
||||||
<value>Habilitat</value>
|
<value>Sí</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Off" xml:space="preserve">
|
<data name="Off" xml:space="preserve">
|
||||||
<value>Desactivat</value>
|
<value>No</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="On" xml:space="preserve">
|
<data name="On" xml:space="preserve">
|
||||||
<value>Activat</value>
|
<value>Sí</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Status" xml:space="preserve">
|
<data name="Status" xml:space="preserve">
|
||||||
<value>Estat</value>
|
<value>Estat</value>
|
||||||
@@ -1103,6 +1103,9 @@ L'escaneig es farà automàticament.</value>
|
|||||||
<data name="Ms" xml:space="preserve">
|
<data name="Ms" xml:space="preserve">
|
||||||
<value>Srta.</value>
|
<value>Srta.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Mx" xml:space="preserve">
|
||||||
|
<value>Mx</value>
|
||||||
|
</data>
|
||||||
<data name="November" xml:space="preserve">
|
<data name="November" xml:space="preserve">
|
||||||
<value>Novembre</value>
|
<value>Novembre</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1620,13 +1623,13 @@ L'escaneig es farà automàticament.</value>
|
|||||||
<value>La vostra sessió ha caducat.</value>
|
<value>La vostra sessió ha caducat.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BiometricsDirection" xml:space="preserve">
|
<data name="BiometricsDirection" xml:space="preserve">
|
||||||
<value>Utilitzeu dades biomètriques per verificar</value>
|
<value>Desbloqueja amb biometria</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Biometrics" xml:space="preserve">
|
<data name="Biometrics" xml:space="preserve">
|
||||||
<value>Dades biomètriques</value>
|
<value>Dades biomètriques</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UseBiometricsToUnlock" xml:space="preserve">
|
<data name="UseBiometricsToUnlock" xml:space="preserve">
|
||||||
<value>Utilitzeu dades biomètriques per desbloquejar</value>
|
<value>Desbloqueja amb biometria</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccessibilityOverlayPermissionAlert" xml:space="preserve">
|
<data name="AccessibilityOverlayPermissionAlert" xml:space="preserve">
|
||||||
<value>Bitwarden necessita atenció: vegeu "Servei d'accessibilitat d'emplenament automàtic" de la configuració de Bitwarden</value>
|
<value>Bitwarden necessita atenció: vegeu "Servei d'accessibilitat d'emplenament automàtic" de la configuració de Bitwarden</value>
|
||||||
@@ -1828,7 +1831,7 @@ L'escaneig es farà automàticament.</value>
|
|||||||
<value>Serveis d'emplenament automàtic</value>
|
<value>Serveis d'emplenament automàtic</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="InlineAutofill" xml:space="preserve">
|
<data name="InlineAutofill" xml:space="preserve">
|
||||||
<value>Utilitza l'emplenament automàtic en línia</value>
|
<value>Utilitza l'emplenament automàtic integrat</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="InlineAutofillDescription" xml:space="preserve">
|
<data name="InlineAutofillDescription" xml:space="preserve">
|
||||||
<value>Utilitzeu l'emplenament automàtic en línia si l'IME (teclat) seleccionat l'admet. Si la vostra configuració no és compatible (o aquesta opció està desactivada), s'utilitzarà la superposició d'emplenament automàtic per defecte.</value>
|
<value>Utilitzeu l'emplenament automàtic en línia si l'IME (teclat) seleccionat l'admet. Si la vostra configuració no és compatible (o aquesta opció està desactivada), s'utilitzarà la superposició d'emplenament automàtic per defecte.</value>
|
||||||
@@ -2299,9 +2302,6 @@ L'escaneig es farà automàticament.</value>
|
|||||||
<value>Una vegada introduïda la clau correctament,
|
<value>Una vegada introduïda la clau correctament,
|
||||||
seleccioneu Afegeix TOTP per emmagatzemar la clau de manera segura</value>
|
seleccioneu Afegeix TOTP per emmagatzemar la clau de manera segura</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
|
|
||||||
<value></value>
|
|
||||||
</data>
|
|
||||||
<data name="NeverLockWarning" xml:space="preserve">
|
<data name="NeverLockWarning" xml:space="preserve">
|
||||||
<value>Si configureu les opcions de bloqueig a "Mai", la vostra caixa forta està disponible per a qualsevol persona amb accés al vostre dispositiu. Si utilitzeu aquesta opció, hauríeu d'assegurar-vos de mantenir el vostre dispositiu correctament protegit.</value>
|
<value>Si configureu les opcions de bloqueig a "Mai", la vostra caixa forta està disponible per a qualsevol persona amb accés al vostre dispositiu. Si utilitzeu aquesta opció, hauríeu d'assegurar-vos de mantenir el vostre dispositiu correctament protegit.</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2422,6 +2422,14 @@ seleccioneu Afegeix TOTP per emmagatzemar la clau de manera segura</value>
|
|||||||
<value>SimpleLogin</value>
|
<value>SimpleLogin</value>
|
||||||
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DuckDuckGo" xml:space="preserve">
|
||||||
|
<value>DuckDuckGo</value>
|
||||||
|
<comment>"DuckDuckGo" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Fastmail" xml:space="preserve">
|
||||||
|
<value>Fastmail</value>
|
||||||
|
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="APIAccessToken" xml:space="preserve">
|
<data name="APIAccessToken" xml:space="preserve">
|
||||||
<value>Token d'accés a l'API</value>
|
<value>Token d'accés a l'API</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2452,6 +2460,9 @@ seleccioneu Afegeix TOTP per emmagatzemar la clau de manera segura</value>
|
|||||||
<data name="Random" xml:space="preserve">
|
<data name="Random" xml:space="preserve">
|
||||||
<value>Aleatori</value>
|
<value>Aleatori</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectToWatch" xml:space="preserve">
|
||||||
|
<value>Connecta't a Watch</value>
|
||||||
|
</data>
|
||||||
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
||||||
<value>Divulgació del servei d'accessibilitat</value>
|
<value>Divulgació del servei d'accessibilitat</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2488,7 +2499,7 @@ Voleu canviar a aquest compte?</value>
|
|||||||
<value>Inicia sessió amb la contrasenya mestra</value>
|
<value>Inicia sessió amb la contrasenya mestra</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInWithAnotherDevice" xml:space="preserve">
|
<data name="LogInWithAnotherDevice" xml:space="preserve">
|
||||||
<value>Inicia sessió amb un altre dispositiu</value>
|
<value>Inici de sessió amb un altre dispositiu</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInInitiated" xml:space="preserve">
|
<data name="LogInInitiated" xml:space="preserve">
|
||||||
<value>S'ha iniciat la sessió</value>
|
<value>S'ha iniciat la sessió</value>
|
||||||
@@ -2511,4 +2522,58 @@ Voleu canviar a aquest compte?</value>
|
|||||||
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
||||||
<value>Aquesta sol·licitud ja no és vàlida</value>
|
<value>Aquesta sol·licitud ja no és vàlida</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Sol·licituds d'inici de sessió pendents</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeclineAllRequests" xml:space="preserve">
|
||||||
|
<value>Rebutja totes les sol·licituds</value>
|
||||||
|
</data>
|
||||||
|
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Esteu segur que voleu rebutjar totes les sol·licituds d'inici de sessió pendents?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequestsDeclined" xml:space="preserve">
|
||||||
|
<value>Sol·licituds rebutjades</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoPendingRequests" xml:space="preserve">
|
||||||
|
<value>Cap sol·licitud pendent</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
|
||||||
|
<value>Habilita el permís de la càmera per utilitzar l'escàner</value>
|
||||||
|
</data>
|
||||||
|
<data name="Important" xml:space="preserve">
|
||||||
|
<value>Important</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
|
||||||
|
<value>La vostra contrasenya mestra no es pot recuperar si l'oblideu! {0} caràcters com a mínim.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakMasterPassword" xml:space="preserve">
|
||||||
|
<value>Contrasenya mestra poc segura</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
|
||||||
|
<value>S'ha identificat una contrasenya feble. Utilitzeu una contrasenya segura per protegir el vostre compte. Esteu segur que voleu utilitzar una contrasenya feble?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Weak" xml:space="preserve">
|
||||||
|
<value>Poc segura</value>
|
||||||
|
</data>
|
||||||
|
<data name="Good" xml:space="preserve">
|
||||||
|
<value>Bona</value>
|
||||||
|
</data>
|
||||||
|
<data name="Strong" xml:space="preserve">
|
||||||
|
<value>Forta</value>
|
||||||
|
</data>
|
||||||
|
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
|
||||||
|
<value>Comproveu les infraccions de dades conegudes per a aquesta contrasenya</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Contrasenya mestra exposada</value>
|
||||||
|
</data>
|
||||||
|
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>S'ha trobat la contrasenya en una filtració de dades. Utilitzeu una contrasenya única per protegir el vostre compte. Esteu segur que voleu utilitzar una contrasenya exposada?</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Contrasenya mestra exposada i poc segura</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Contrasenya feble identificada i trobada en una filtració de dades. Utilitzeu una contrasenya única i segura per protegir el vostre compte. Esteu segur que voleu utilitzar aquesta contrasenya?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -376,7 +376,7 @@
|
|||||||
</data>
|
</data>
|
||||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||||
<value>{0} bylo zkopírováno.</value>
|
<value>{0} bylo zkopírováno.</value>
|
||||||
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment>
|
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerifyFingerprint" xml:space="preserve">
|
<data name="VerifyFingerprint" xml:space="preserve">
|
||||||
<value>Ověření otisku prstu</value>
|
<value>Ověření otisku prstu</value>
|
||||||
@@ -1103,6 +1103,9 @@ Načtení proběhne automaticky.</value>
|
|||||||
<data name="Ms" xml:space="preserve">
|
<data name="Ms" xml:space="preserve">
|
||||||
<value>Slečna</value>
|
<value>Slečna</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Mx" xml:space="preserve">
|
||||||
|
<value>Mx</value>
|
||||||
|
</data>
|
||||||
<data name="November" xml:space="preserve">
|
<data name="November" xml:space="preserve">
|
||||||
<value>Listopad</value>
|
<value>Listopad</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2299,9 +2302,6 @@ Načtení proběhne automaticky.</value>
|
|||||||
<value>Once the key is successfully entered,
|
<value>Once the key is successfully entered,
|
||||||
select Add TOTP to store the key safely</value>
|
select Add TOTP to store the key safely</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
|
|
||||||
<value></value>
|
|
||||||
</data>
|
|
||||||
<data name="NeverLockWarning" xml:space="preserve">
|
<data name="NeverLockWarning" xml:space="preserve">
|
||||||
<value>Nastavení zámku na „Nikdy“ ponechá váš trezor k dispozici komukoliv s přístupem k vašemu zařízení. Používáte-li tuto možnost, měli byste zajistit, aby vaše zařízení bylo náležitě chráněno.</value>
|
<value>Nastavení zámku na „Nikdy“ ponechá váš trezor k dispozici komukoliv s přístupem k vašemu zařízení. Používáte-li tuto možnost, měli byste zajistit, aby vaše zařízení bylo náležitě chráněno.</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2422,6 +2422,14 @@ select Add TOTP to store the key safely</value>
|
|||||||
<value>SimpleLogin</value>
|
<value>SimpleLogin</value>
|
||||||
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DuckDuckGo" xml:space="preserve">
|
||||||
|
<value>DuckDuckGo</value>
|
||||||
|
<comment>"DuckDuckGo" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Fastmail" xml:space="preserve">
|
||||||
|
<value>Fastmail</value>
|
||||||
|
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="APIAccessToken" xml:space="preserve">
|
<data name="APIAccessToken" xml:space="preserve">
|
||||||
<value>Přístupový token API</value>
|
<value>Přístupový token API</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2452,6 +2460,9 @@ select Add TOTP to store the key safely</value>
|
|||||||
<data name="Random" xml:space="preserve">
|
<data name="Random" xml:space="preserve">
|
||||||
<value>Náhodně</value>
|
<value>Náhodně</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectToWatch" xml:space="preserve">
|
||||||
|
<value>Connect to Watch</value>
|
||||||
|
</data>
|
||||||
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
||||||
<value>Accessibility Service Disclosure</value>
|
<value>Accessibility Service Disclosure</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2511,4 +2522,58 @@ Chcete se přepnout na tento účet?</value>
|
|||||||
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
||||||
<value>Tento požadavek již není platný</value>
|
<value>Tento požadavek již není platný</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Pending login requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeclineAllRequests" xml:space="preserve">
|
||||||
|
<value>Decline all requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Are you sure you want to decline all pending login requests?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequestsDeclined" xml:space="preserve">
|
||||||
|
<value>Requests declined</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoPendingRequests" xml:space="preserve">
|
||||||
|
<value>No pending requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
|
||||||
|
<value>Enable camera permission to use the scanner</value>
|
||||||
|
</data>
|
||||||
|
<data name="Important" xml:space="preserve">
|
||||||
|
<value>Important</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
|
||||||
|
<value>Your master password cannot be recovered if you forget it! {0} characters minimum.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakMasterPassword" xml:space="preserve">
|
||||||
|
<value>Weak Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
|
||||||
|
<value>Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Weak" xml:space="preserve">
|
||||||
|
<value>Weak</value>
|
||||||
|
</data>
|
||||||
|
<data name="Good" xml:space="preserve">
|
||||||
|
<value>Good</value>
|
||||||
|
</data>
|
||||||
|
<data name="Strong" xml:space="preserve">
|
||||||
|
<value>Strong</value>
|
||||||
|
</data>
|
||||||
|
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
|
||||||
|
<value>Check known data breaches for this password</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Weak and Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -376,7 +376,7 @@
|
|||||||
</data>
|
</data>
|
||||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||||
<value>{0} kopieret</value>
|
<value>{0} kopieret</value>
|
||||||
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment>
|
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerifyFingerprint" xml:space="preserve">
|
<data name="VerifyFingerprint" xml:space="preserve">
|
||||||
<value>Verificér fingeraftryk</value>
|
<value>Verificér fingeraftryk</value>
|
||||||
@@ -1103,6 +1103,9 @@ Skanning vil ske automatisk.</value>
|
|||||||
<data name="Ms" xml:space="preserve">
|
<data name="Ms" xml:space="preserve">
|
||||||
<value>Frk</value>
|
<value>Frk</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Mx" xml:space="preserve">
|
||||||
|
<value>Mx</value>
|
||||||
|
</data>
|
||||||
<data name="November" xml:space="preserve">
|
<data name="November" xml:space="preserve">
|
||||||
<value>November</value>
|
<value>November</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1762,7 +1765,7 @@ Skanning vil ske automatisk.</value>
|
|||||||
<value>Synkronisering af boks med træk nedad-gestus.</value>
|
<value>Synkronisering af boks med træk nedad-gestus.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInSso" xml:space="preserve">
|
<data name="LogInSso" xml:space="preserve">
|
||||||
<value>Virksomheds Single Sign On</value>
|
<value>Virksomheds Single Sign-On</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInSsoSummary" xml:space="preserve">
|
<data name="LogInSsoSummary" xml:space="preserve">
|
||||||
<value>Log hurtigt ind vha. din organisations single sign-on portal. Angiv din organisations identifikator for at begynde.</value>
|
<value>Log hurtigt ind vha. din organisations single sign-on portal. Angiv din organisations identifikator for at begynde.</value>
|
||||||
@@ -2299,9 +2302,6 @@ Skanning vil ske automatisk.</value>
|
|||||||
<value>Når nøglen er angivet,
|
<value>Når nøglen er angivet,
|
||||||
vælg Tilføj TOTP for at gemme nøglen sikkert</value>
|
vælg Tilføj TOTP for at gemme nøglen sikkert</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
|
|
||||||
<value></value>
|
|
||||||
</data>
|
|
||||||
<data name="NeverLockWarning" xml:space="preserve">
|
<data name="NeverLockWarning" xml:space="preserve">
|
||||||
<value>Sættes låseindstillingen til “Aldrig”, er din boks tilgængelig for alle med adgang til enheden. Bruges denne mulighed, så vær sikker på, at din enhed er ordentligt beskyttet.</value>
|
<value>Sættes låseindstillingen til “Aldrig”, er din boks tilgængelig for alle med adgang til enheden. Bruges denne mulighed, så vær sikker på, at din enhed er ordentligt beskyttet.</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2422,6 +2422,14 @@ vælg Tilføj TOTP for at gemme nøglen sikkert</value>
|
|||||||
<value>SimpleLogin</value>
|
<value>SimpleLogin</value>
|
||||||
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DuckDuckGo" xml:space="preserve">
|
||||||
|
<value>DuckDuckGo</value>
|
||||||
|
<comment>"DuckDuckGo" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Fastmail" xml:space="preserve">
|
||||||
|
<value>Fastmail</value>
|
||||||
|
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="APIAccessToken" xml:space="preserve">
|
<data name="APIAccessToken" xml:space="preserve">
|
||||||
<value>API-adgangstoken</value>
|
<value>API-adgangstoken</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2452,6 +2460,9 @@ vælg Tilføj TOTP for at gemme nøglen sikkert</value>
|
|||||||
<data name="Random" xml:space="preserve">
|
<data name="Random" xml:space="preserve">
|
||||||
<value>Tilfældig</value>
|
<value>Tilfældig</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectToWatch" xml:space="preserve">
|
||||||
|
<value>Opret forbindelse til Watch</value>
|
||||||
|
</data>
|
||||||
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
||||||
<value>Oplysninger om tilgængelighedstjeneste</value>
|
<value>Oplysninger om tilgængelighedstjeneste</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2511,4 +2522,58 @@ Vil du skifte til denne konto?</value>
|
|||||||
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
||||||
<value>Anmodningen er ikke længere gyldig</value>
|
<value>Anmodningen er ikke længere gyldig</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Afventende login-anmodninger</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeclineAllRequests" xml:space="preserve">
|
||||||
|
<value>Afvis alle anmodninger</value>
|
||||||
|
</data>
|
||||||
|
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Sikker på, at alle afventende login-anmodninger skal afvises?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequestsDeclined" xml:space="preserve">
|
||||||
|
<value>Anmodninger afvist</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoPendingRequests" xml:space="preserve">
|
||||||
|
<value>Ingen afventende anmodninger</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
|
||||||
|
<value>Tildel kameratilladelse for brug af skanneren</value>
|
||||||
|
</data>
|
||||||
|
<data name="Important" xml:space="preserve">
|
||||||
|
<value>Vigtigt</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
|
||||||
|
<value>Hovedadgangskoden kan ikke gendannes, hvis du glemmer den! {0} tegn minimum.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakMasterPassword" xml:space="preserve">
|
||||||
|
<value>Svag hovedadgangskode</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
|
||||||
|
<value>Svag adgangskode identificeret. Brug en stærk adgangskode til at beskytte din konto. Sikker på, at du vil bruge en svag adgangskode?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Weak" xml:space="preserve">
|
||||||
|
<value>Svag</value>
|
||||||
|
</data>
|
||||||
|
<data name="Good" xml:space="preserve">
|
||||||
|
<value>God</value>
|
||||||
|
</data>
|
||||||
|
<data name="Strong" xml:space="preserve">
|
||||||
|
<value>Stærk</value>
|
||||||
|
</data>
|
||||||
|
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
|
||||||
|
<value>Tjek kendte datalæk for denne adgangskode</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Kompromitteret hovedadgangskode</value>
|
||||||
|
</data>
|
||||||
|
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Adgangskode fundet i datalæk. Brug en unik adgangskode til at beskytte din konto. Sikker på, at du vil bruge en kompromitteret adgangskode?</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Svag eller kompromitteret hovedadgangskode</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Svag adgangskode identificeret og fundet i datalæk. Brug en unik adgangskode til at beskytte din konto. Sikker på, at du vil bruge denne adgangskode?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -376,7 +376,7 @@
|
|||||||
</data>
|
</data>
|
||||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||||
<value>{0} wurde kopiert</value>
|
<value>{0} wurde kopiert</value>
|
||||||
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment>
|
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerifyFingerprint" xml:space="preserve">
|
<data name="VerifyFingerprint" xml:space="preserve">
|
||||||
<value>Fingerabdruck überprüfen</value>
|
<value>Fingerabdruck überprüfen</value>
|
||||||
@@ -1103,6 +1103,9 @@ Das Scannen erfolgt automatisch.</value>
|
|||||||
<data name="Ms" xml:space="preserve">
|
<data name="Ms" xml:space="preserve">
|
||||||
<value>Frau</value>
|
<value>Frau</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Mx" xml:space="preserve">
|
||||||
|
<value>Divers</value>
|
||||||
|
</data>
|
||||||
<data name="November" xml:space="preserve">
|
<data name="November" xml:space="preserve">
|
||||||
<value>November</value>
|
<value>November</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2298,9 +2301,6 @@ Das Scannen erfolgt automatisch.</value>
|
|||||||
<data name="OnceTheKeyIsSuccessfullyEntered" xml:space="preserve">
|
<data name="OnceTheKeyIsSuccessfullyEntered" xml:space="preserve">
|
||||||
<value>Sobald der Schlüssel erfolgreich eingegeben wurde, wähle TOTP hinzufügen, um den Schlüssel sicher abzuspeichern</value>
|
<value>Sobald der Schlüssel erfolgreich eingegeben wurde, wähle TOTP hinzufügen, um den Schlüssel sicher abzuspeichern</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
|
|
||||||
<value></value>
|
|
||||||
</data>
|
|
||||||
<data name="NeverLockWarning" xml:space="preserve">
|
<data name="NeverLockWarning" xml:space="preserve">
|
||||||
<value>Wenn du deine Sperroptionen auf „Nie“ einstellst, bleibt dein Tresor für jeden zugänglich, der Zugriff auf dein Gerät hat. Wenn du diese Option verwendest, solltest du sicherstellen, dass du dein Gerät angemessen schützt.</value>
|
<value>Wenn du deine Sperroptionen auf „Nie“ einstellst, bleibt dein Tresor für jeden zugänglich, der Zugriff auf dein Gerät hat. Wenn du diese Option verwendest, solltest du sicherstellen, dass du dein Gerät angemessen schützt.</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2317,7 +2317,7 @@ Das Scannen erfolgt automatisch.</value>
|
|||||||
<value>Bist du sicher, dass du die Bildschirmaufnahme aktivieren möchtest?</value>
|
<value>Bist du sicher, dass du die Bildschirmaufnahme aktivieren möchtest?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInRequested" xml:space="preserve">
|
<data name="LogInRequested" xml:space="preserve">
|
||||||
<value>Zugangsdaten angefordert</value>
|
<value>Anmeldung angefordert</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AreYouTryingToLogIn" xml:space="preserve">
|
<data name="AreYouTryingToLogIn" xml:space="preserve">
|
||||||
<value>Versuchst du dich anzumelden?</value>
|
<value>Versuchst du dich anzumelden?</value>
|
||||||
@@ -2421,6 +2421,14 @@ Das Scannen erfolgt automatisch.</value>
|
|||||||
<value>SimpleLogin</value>
|
<value>SimpleLogin</value>
|
||||||
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DuckDuckGo" xml:space="preserve">
|
||||||
|
<value>DuckDuckGo</value>
|
||||||
|
<comment>"DuckDuckGo" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Fastmail" xml:space="preserve">
|
||||||
|
<value>Fastmail</value>
|
||||||
|
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="APIAccessToken" xml:space="preserve">
|
<data name="APIAccessToken" xml:space="preserve">
|
||||||
<value>API-Zugangs-Token</value>
|
<value>API-Zugangs-Token</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2451,6 +2459,9 @@ Das Scannen erfolgt automatisch.</value>
|
|||||||
<data name="Random" xml:space="preserve">
|
<data name="Random" xml:space="preserve">
|
||||||
<value>Zufällig</value>
|
<value>Zufällig</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectToWatch" xml:space="preserve">
|
||||||
|
<value>Mit Uhr verbinden</value>
|
||||||
|
</data>
|
||||||
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
||||||
<value>Bedienungshilfen Offenlegung</value>
|
<value>Bedienungshilfen Offenlegung</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2510,4 +2521,58 @@ Möchtest du zu diesem Konto wechseln?</value>
|
|||||||
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
||||||
<value>Diese Anfrage ist nicht mehr gültig</value>
|
<value>Diese Anfrage ist nicht mehr gültig</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Ausstehende Anmeldeanfragen</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeclineAllRequests" xml:space="preserve">
|
||||||
|
<value>Alle Anfragen ablehnen</value>
|
||||||
|
</data>
|
||||||
|
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Bist du sicher, dass du alle ausstehenden Anmeldeanfragen ablehnen möchtest?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequestsDeclined" xml:space="preserve">
|
||||||
|
<value>Anfragen abgelehnt</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoPendingRequests" xml:space="preserve">
|
||||||
|
<value>Keine ausstehenden Anfragen</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
|
||||||
|
<value>Kamerazugriff aktivieren, um den Scanner zu verwenden</value>
|
||||||
|
</data>
|
||||||
|
<data name="Important" xml:space="preserve">
|
||||||
|
<value>Wichtig</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
|
||||||
|
<value>Dein Master-Passwort kann nicht wiederhergestellt werden, wenn du es vergisst! Mindestens {0} Zeichen.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakMasterPassword" xml:space="preserve">
|
||||||
|
<value>Schwaches Master-Passwort</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
|
||||||
|
<value>Schwaches Passwort erkannt. Verwende ein starkes Passwort, um dein Konto zu schützen. Bist du sicher, dass du ein schwaches Passwort verwenden möchtest?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Weak" xml:space="preserve">
|
||||||
|
<value>Schwach</value>
|
||||||
|
</data>
|
||||||
|
<data name="Good" xml:space="preserve">
|
||||||
|
<value>Gut</value>
|
||||||
|
</data>
|
||||||
|
<data name="Strong" xml:space="preserve">
|
||||||
|
<value>Stark</value>
|
||||||
|
</data>
|
||||||
|
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
|
||||||
|
<value>Bekannte Datendiebstähle auf dieses Passwort überprüfen</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Kompromittiertes Master-Passwort</value>
|
||||||
|
</data>
|
||||||
|
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Passwort in einem Datendiebstahl gefunden. Verwende ein einzigartiges Passwort, um dein Konto zu schützen. Bist du sicher, dass du ein kompromittiertes Passwort verwenden möchtest?</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Schwaches und kompromittiertes Master-Passwort</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Schwaches Passwort erkannt und in einem Datendiebstahl gefunden. Verwende ein starkes und einzigartiges Passwort, um dein Konto zu schützen. Bist du sicher, dass du dieses Passwort verwenden möchtest?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -377,7 +377,7 @@
|
|||||||
</data>
|
</data>
|
||||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||||
<value>{0} έχει αντιγραφεί.</value>
|
<value>{0} έχει αντιγραφεί.</value>
|
||||||
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment>
|
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerifyFingerprint" xml:space="preserve">
|
<data name="VerifyFingerprint" xml:space="preserve">
|
||||||
<value>Επαλήθευση Δακτυλικού Αποτυπώματος</value>
|
<value>Επαλήθευση Δακτυλικού Αποτυπώματος</value>
|
||||||
@@ -1103,6 +1103,9 @@
|
|||||||
<data name="Ms" xml:space="preserve">
|
<data name="Ms" xml:space="preserve">
|
||||||
<value>Κα</value>
|
<value>Κα</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Mx" xml:space="preserve">
|
||||||
|
<value>Mx</value>
|
||||||
|
</data>
|
||||||
<data name="November" xml:space="preserve">
|
<data name="November" xml:space="preserve">
|
||||||
<value>Νοέμβριος</value>
|
<value>Νοέμβριος</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2299,9 +2302,6 @@
|
|||||||
<value>Μόλις το κλειδί εισαχθεί με επιτυχία,
|
<value>Μόλις το κλειδί εισαχθεί με επιτυχία,
|
||||||
επιλέξτε Προσθήκη TOTP για να αποθηκεύσετε το κλειδί με ασφάλεια</value>
|
επιλέξτε Προσθήκη TOTP για να αποθηκεύσετε το κλειδί με ασφάλεια</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
|
|
||||||
<value></value>
|
|
||||||
</data>
|
|
||||||
<data name="NeverLockWarning" xml:space="preserve">
|
<data name="NeverLockWarning" xml:space="preserve">
|
||||||
<value>Ρυθμίζοντας τις επιλογές κλειδώματος σε “Ποτέ” κρατά τη κρύπτη σας διαθέσιμη σε οποιονδήποτε με πρόσβαση στη συσκευή σας. Εάν χρησιμοποιείτε αυτήν την επιλογή, θα πρέπει να διασφαλίσετε ότι διατηρείτε τη συσκευή σας σωστά προστατευμένη.</value>
|
<value>Ρυθμίζοντας τις επιλογές κλειδώματος σε “Ποτέ” κρατά τη κρύπτη σας διαθέσιμη σε οποιονδήποτε με πρόσβαση στη συσκευή σας. Εάν χρησιμοποιείτε αυτήν την επιλογή, θα πρέπει να διασφαλίσετε ότι διατηρείτε τη συσκευή σας σωστά προστατευμένη.</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2422,6 +2422,14 @@
|
|||||||
<value>SimpleLogin</value>
|
<value>SimpleLogin</value>
|
||||||
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DuckDuckGo" xml:space="preserve">
|
||||||
|
<value>DuckDuckGo</value>
|
||||||
|
<comment>"DuckDuckGo" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Fastmail" xml:space="preserve">
|
||||||
|
<value>Fastmail</value>
|
||||||
|
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="APIAccessToken" xml:space="preserve">
|
<data name="APIAccessToken" xml:space="preserve">
|
||||||
<value>API Access Token</value>
|
<value>API Access Token</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2452,20 +2460,23 @@
|
|||||||
<data name="Random" xml:space="preserve">
|
<data name="Random" xml:space="preserve">
|
||||||
<value>Τυχαίο</value>
|
<value>Τυχαίο</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectToWatch" xml:space="preserve">
|
||||||
|
<value>Σύνδεση με το ρολόι</value>
|
||||||
|
</data>
|
||||||
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
||||||
<value>Γνωστοποίηση Υπηρεσίας Προσβασιμότητας</value>
|
<value>Γνωστοποίηση Υπηρεσίας Προσβασιμότητας</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccessibilityDisclosureText" xml:space="preserve">
|
<data name="AccessibilityDisclosureText" xml:space="preserve">
|
||||||
<value>Bitwarden uses the Accessibility Service to search for login fields in apps and websites, then establish the appropriate field IDs for entering a username & password when a match for the app or site is found. We do not store any of the information presented to us by the service, nor do we make any attempt to control any on-screen elements beyond text entry of credentials.</value>
|
<value>Το Bitwarden χρησιμοποιεί την Υπηρεσία Προσβασιμότητας για να αναζητήσει πεδία σύνδεσης σε εφαρμογές και ιστότοπους και στη συνέχεια να δημιουργήσει τα κατάλληλα αναγνωριστικά πεδίου για την εισαγωγή ονόματος χρήστη και κωδικού πρόσβασης όταν βρεθεί αντιστοιχία για την εφαρμογή ή τον ιστότοπο. Δεν αποθηκεύουμε καμία από τις πληροφορίες που μας παρέχονται από την υπηρεσία, ούτε κάνουμε καμία προσπάθεια ελέγχου οποιωνδήποτε στοιχείων στην οθόνη πέραν της εισαγωγής του κειμένου των διαπιστευτηρίων.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Accept" xml:space="preserve">
|
<data name="Accept" xml:space="preserve">
|
||||||
<value>Accept</value>
|
<value>Αποδοχή</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Decline" xml:space="preserve">
|
<data name="Decline" xml:space="preserve">
|
||||||
<value>Decline</value>
|
<value>Απόρριψη</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LoginRequestHasAlreadyExpired" xml:space="preserve">
|
<data name="LoginRequestHasAlreadyExpired" xml:space="preserve">
|
||||||
<value>Login request has already expired.</value>
|
<value>Το αίτημα σύνδεσης έχει ήδη λήξει.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve">
|
<data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve">
|
||||||
<value>Login attempt from:
|
<value>Login attempt from:
|
||||||
@@ -2476,25 +2487,25 @@ Do you want to switch to this account?</value>
|
|||||||
<value>New around here?</value>
|
<value>New around here?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GetMasterPasswordwordHint" xml:space="preserve">
|
<data name="GetMasterPasswordwordHint" xml:space="preserve">
|
||||||
<value>Get master password hint</value>
|
<value>Λάβετε υπόδειξη κύριου κωδικού</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LoggingInAsX" xml:space="preserve">
|
<data name="LoggingInAsX" xml:space="preserve">
|
||||||
<value>Logging in as {0}</value>
|
<value>Σύνδεση ως {0}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NotYou" xml:space="preserve">
|
<data name="NotYou" xml:space="preserve">
|
||||||
<value>Not you?</value>
|
<value>Δεν είστε εσείς;</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInWithMasterPassword" xml:space="preserve">
|
<data name="LogInWithMasterPassword" xml:space="preserve">
|
||||||
<value>Log in with master password</value>
|
<value>Σύνδεση με κύριο κωδικό</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInWithAnotherDevice" xml:space="preserve">
|
<data name="LogInWithAnotherDevice" xml:space="preserve">
|
||||||
<value>Log In with another device</value>
|
<value>Σύνδεση με τη χρήση συσκευής</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInInitiated" xml:space="preserve">
|
<data name="LogInInitiated" xml:space="preserve">
|
||||||
<value>Log in initiated</value>
|
<value>Η σύνδεση ξεκίνησε</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
|
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
|
||||||
<value>A notification has been sent to your device.</value>
|
<value>Μια ειδοποίηση έχει σταλεί στη συσκευή σας.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
|
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
|
||||||
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
|
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
|
||||||
@@ -2511,4 +2522,58 @@ Do you want to switch to this account?</value>
|
|||||||
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
||||||
<value>This request is no longer valid</value>
|
<value>This request is no longer valid</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Pending login requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeclineAllRequests" xml:space="preserve">
|
||||||
|
<value>Απόρριψη όλων των αιτημάτων</value>
|
||||||
|
</data>
|
||||||
|
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Are you sure you want to decline all pending login requests?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequestsDeclined" xml:space="preserve">
|
||||||
|
<value>Requests declined</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoPendingRequests" xml:space="preserve">
|
||||||
|
<value>No pending requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
|
||||||
|
<value>Enable camera permission to use the scanner</value>
|
||||||
|
</data>
|
||||||
|
<data name="Important" xml:space="preserve">
|
||||||
|
<value>Σημαντικό</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
|
||||||
|
<value>Your master password cannot be recovered if you forget it! {0} characters minimum.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakMasterPassword" xml:space="preserve">
|
||||||
|
<value>Αδύναμος Κύριος Κωδικός</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
|
||||||
|
<value>Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Weak" xml:space="preserve">
|
||||||
|
<value>Αδύναμος</value>
|
||||||
|
</data>
|
||||||
|
<data name="Good" xml:space="preserve">
|
||||||
|
<value>Καλός</value>
|
||||||
|
</data>
|
||||||
|
<data name="Strong" xml:space="preserve">
|
||||||
|
<value>Ισχυρός</value>
|
||||||
|
</data>
|
||||||
|
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
|
||||||
|
<value>Check known data breaches for this password</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Εκτεθειμένος Κύριος Κωδικός Πρόσβασης</value>
|
||||||
|
</data>
|
||||||
|
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Weak and Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -376,7 +376,7 @@
|
|||||||
</data>
|
</data>
|
||||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||||
<value>{0} copied</value>
|
<value>{0} copied</value>
|
||||||
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment>
|
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerifyFingerprint" xml:space="preserve">
|
<data name="VerifyFingerprint" xml:space="preserve">
|
||||||
<value>Verify fingerprint</value>
|
<value>Verify fingerprint</value>
|
||||||
@@ -471,19 +471,19 @@
|
|||||||
<value>Edit item</value>
|
<value>Edit item</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnableAutomaticSyncing" xml:space="preserve">
|
<data name="EnableAutomaticSyncing" xml:space="preserve">
|
||||||
<value>Enable automatic syncing</value>
|
<value>Allow automatic syncing</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnterEmailForHint" xml:space="preserve">
|
<data name="EnterEmailForHint" xml:space="preserve">
|
||||||
<value>Enter your account email address to receive your master password hint.</value>
|
<value>Enter your account email address to receive your master password hint.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExntesionReenable" xml:space="preserve">
|
<data name="ExntesionReenable" xml:space="preserve">
|
||||||
<value>Re-enable app extension</value>
|
<value>Reactivate app extension</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExtensionAlmostDone" xml:space="preserve">
|
<data name="ExtensionAlmostDone" xml:space="preserve">
|
||||||
<value>Almost done!</value>
|
<value>Almost done!</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExtensionEnable" xml:space="preserve">
|
<data name="ExtensionEnable" xml:space="preserve">
|
||||||
<value>Enable app extension</value>
|
<value>Activate app extension</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExtensionInSafari" xml:space="preserve">
|
<data name="ExtensionInSafari" xml:space="preserve">
|
||||||
<value>In Safari, find Bitwarden using the share icon (hint: scroll to the right on the bottom row of the menu).</value>
|
<value>In Safari, find Bitwarden using the share icon (hint: scroll to the right on the bottom row of the menu).</value>
|
||||||
@@ -604,7 +604,7 @@
|
|||||||
<value>Never</value>
|
<value>Never</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NewItemCreated" xml:space="preserve">
|
<data name="NewItemCreated" xml:space="preserve">
|
||||||
<value>New item created.</value>
|
<value>Item added</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NoFavorites" xml:space="preserve">
|
<data name="NoFavorites" xml:space="preserve">
|
||||||
<value>There are no favourites in your vault.</value>
|
<value>There are no favourites in your vault.</value>
|
||||||
@@ -632,7 +632,7 @@
|
|||||||
<value>Other</value>
|
<value>Other</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PasswordGenerated" xml:space="preserve">
|
<data name="PasswordGenerated" xml:space="preserve">
|
||||||
<value>Password generated.</value>
|
<value>Password generated</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PasswordGenerator" xml:space="preserve">
|
<data name="PasswordGenerator" xml:space="preserve">
|
||||||
<value>Password generator</value>
|
<value>Password generator</value>
|
||||||
@@ -647,7 +647,7 @@
|
|||||||
<value>Are you sure you want to overwrite the current password?</value>
|
<value>Are you sure you want to overwrite the current password?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PushNotificationAlert" xml:space="preserve">
|
<data name="PushNotificationAlert" xml:space="preserve">
|
||||||
<value>Bitwarden keeps your vault automatically synced by using push notifications. For the best possible experience, please select "Allow" on the following prompt when asked to enable push notifications.</value>
|
<value>Bitwarden keeps your vault automatically synced by using push notifications. For the best possible experience, please select "Allow" on the following prompt when asked to allow push notifications.</value>
|
||||||
<comment>Push notifications for apple products</comment>
|
<comment>Push notifications for apple products</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="RateTheApp" xml:space="preserve">
|
<data name="RateTheApp" xml:space="preserve">
|
||||||
@@ -663,7 +663,7 @@
|
|||||||
<value>Re-type master password</value>
|
<value>Re-type master password</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SearchVault" xml:space="preserve">
|
<data name="SearchVault" xml:space="preserve">
|
||||||
<value>Search Vault</value>
|
<value>Search vault</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Security" xml:space="preserve">
|
<data name="Security" xml:space="preserve">
|
||||||
<value>Security</value>
|
<value>Security</value>
|
||||||
@@ -681,7 +681,7 @@
|
|||||||
<value>Item information</value>
|
<value>Item information</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ItemUpdated" xml:space="preserve">
|
<data name="ItemUpdated" xml:space="preserve">
|
||||||
<value>Item updated.</value>
|
<value>Item saved</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Submitting" xml:space="preserve">
|
<data name="Submitting" xml:space="preserve">
|
||||||
<value>Submitting...</value>
|
<value>Submitting...</value>
|
||||||
@@ -692,10 +692,10 @@
|
|||||||
<comment>Message shown when interacting with the server</comment>
|
<comment>Message shown when interacting with the server</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="SyncingComplete" xml:space="preserve">
|
<data name="SyncingComplete" xml:space="preserve">
|
||||||
<value>Syncing complete.</value>
|
<value>Syncing complete</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SyncingFailed" xml:space="preserve">
|
<data name="SyncingFailed" xml:space="preserve">
|
||||||
<value>Syncing failed.</value>
|
<value>Syncing failed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SyncVaultNow" xml:space="preserve">
|
<data name="SyncVaultNow" xml:space="preserve">
|
||||||
<value>Sync vault now</value>
|
<value>Sync vault now</value>
|
||||||
@@ -708,7 +708,7 @@
|
|||||||
<value>Two-step login</value>
|
<value>Two-step login</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TwoStepLoginConfirmation" xml:space="preserve">
|
<data name="TwoStepLoginConfirmation" xml:space="preserve">
|
||||||
<value>Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?</value>
|
<value>Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be set up on the bitwarden.com web vault. Do you want to visit the website now?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UnlockWith" xml:space="preserve">
|
<data name="UnlockWith" xml:space="preserve">
|
||||||
<value>Unlock with {0}</value>
|
<value>Unlock with {0}</value>
|
||||||
@@ -831,7 +831,7 @@
|
|||||||
<comment>For 2FA whenever there are no available providers on this device.</comment>
|
<comment>For 2FA whenever there are no available providers on this device.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="NoTwoStepAvailable" xml:space="preserve">
|
<data name="NoTwoStepAvailable" xml:space="preserve">
|
||||||
<value>This account has two-step login enabled. However, none of the configured two-step providers are supported on this device. Please use a supported device and/or add additional providers that are better supported across devices (such as an authenticator app).</value>
|
<value>This account has two-step login set up, however, none of the configured two-step providers are supported on this device. Please use a supported device and/or add additional providers that are better supported across devices (such as an authenticator app).</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RecoveryCodeTitle" xml:space="preserve">
|
<data name="RecoveryCodeTitle" xml:space="preserve">
|
||||||
<value>Recovery code</value>
|
<value>Recovery code</value>
|
||||||
@@ -856,7 +856,7 @@
|
|||||||
<comment>For 2FA</comment>
|
<comment>For 2FA</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerificationEmailSent" xml:space="preserve">
|
<data name="VerificationEmailSent" xml:space="preserve">
|
||||||
<value>Verification email sent.</value>
|
<value>Verification email sent</value>
|
||||||
<comment>For 2FA</comment>
|
<comment>For 2FA</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="YubiKeyInstruction" xml:space="preserve">
|
<data name="YubiKeyInstruction" xml:space="preserve">
|
||||||
@@ -1080,7 +1080,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Last name</value>
|
<value>Last name</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FullName" xml:space="preserve">
|
<data name="FullName" xml:space="preserve">
|
||||||
<value>Full Name</value>
|
<value>Full name</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LicenseNumber" xml:space="preserve">
|
<data name="LicenseNumber" xml:space="preserve">
|
||||||
<value>Licence number</value>
|
<value>Licence number</value>
|
||||||
@@ -1103,6 +1103,9 @@ Scanning will happen automatically.</value>
|
|||||||
<data name="Ms" xml:space="preserve">
|
<data name="Ms" xml:space="preserve">
|
||||||
<value>Ms</value>
|
<value>Ms</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Mx" xml:space="preserve">
|
||||||
|
<value>Mx</value>
|
||||||
|
</data>
|
||||||
<data name="November" xml:space="preserve">
|
<data name="November" xml:space="preserve">
|
||||||
<value>November</value>
|
<value>November</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1301,7 +1304,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Access your vault directly from your keyboard to quickly auto-fill passwords.</value>
|
<value>Access your vault directly from your keyboard to quickly auto-fill passwords.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillTurnOn" xml:space="preserve">
|
<data name="AutofillTurnOn" xml:space="preserve">
|
||||||
<value>To enable password auto-fill on your device, follow these instructions:</value>
|
<value>To set up password auto-fill on your device, follow these instructions:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillTurnOn1" xml:space="preserve">
|
<data name="AutofillTurnOn1" xml:space="preserve">
|
||||||
<value>1. Go to the iOS "Settings" app</value>
|
<value>1. Go to the iOS "Settings" app</value>
|
||||||
@@ -1381,10 +1384,10 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Search collection</value>
|
<value>Search collection</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SearchFileSends" xml:space="preserve">
|
<data name="SearchFileSends" xml:space="preserve">
|
||||||
<value>Search File Sends</value>
|
<value>Search file Sends</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SearchTextSends" xml:space="preserve">
|
<data name="SearchTextSends" xml:space="preserve">
|
||||||
<value>Search Text Sends</value>
|
<value>Search text Sends</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SearchGroup" xml:space="preserve">
|
<data name="SearchGroup" xml:space="preserve">
|
||||||
<value>Search {0}</value>
|
<value>Search {0}</value>
|
||||||
@@ -1480,7 +1483,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Unlock</value>
|
<value>Unlock</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UnlockVault" xml:space="preserve">
|
<data name="UnlockVault" xml:space="preserve">
|
||||||
<value>Unlock Vault</value>
|
<value>Unlock vault</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ThirtyMinutes" xml:space="preserve">
|
<data name="ThirtyMinutes" xml:space="preserve">
|
||||||
<value>30 minutes</value>
|
<value>30 minutes</value>
|
||||||
@@ -1553,10 +1556,10 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Default dark theme</value>
|
<value>Default dark theme</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DefaultDarkThemeDescription" xml:space="preserve">
|
<data name="DefaultDarkThemeDescription" xml:space="preserve">
|
||||||
<value>Choose the dark theme to use when using Default (System) theme while your device's dark mode is enabled.</value>
|
<value>Choose the dark theme to use when using Default (System) theme while your device's dark mode is in use.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CopyNotes" xml:space="preserve">
|
<data name="CopyNotes" xml:space="preserve">
|
||||||
<value>Copy Note</value>
|
<value>Copy note</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Exit" xml:space="preserve">
|
<data name="Exit" xml:space="preserve">
|
||||||
<value>Exit</value>
|
<value>Exit</value>
|
||||||
@@ -1595,7 +1598,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>On app restart</value>
|
<value>On app restart</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillServiceNotEnabled" xml:space="preserve">
|
<data name="AutofillServiceNotEnabled" xml:space="preserve">
|
||||||
<value>Auto-fill makes it easy to securely access your Bitwarden vault from other websites and apps. It looks like you have not enabled an auto-fill service for Bitwarden. Enable auto-fill for Bitwarden from the "Settings" screen.</value>
|
<value>Auto-fill makes it easy to securely access your Bitwarden vault from other websites and apps. It looks like you have not set up an auto-fill service for Bitwarden. Set up auto-fill for Bitwarden from the "Settings" screen.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ThemeAppliedOnRestart" xml:space="preserve">
|
<data name="ThemeAppliedOnRestart" xml:space="preserve">
|
||||||
<value>Your theme changes will apply when the app is restarted.</value>
|
<value>Your theme changes will apply when the app is restarted.</value>
|
||||||
@@ -1629,10 +1632,10 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Use biometrics to unlock</value>
|
<value>Use biometrics to unlock</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccessibilityOverlayPermissionAlert" xml:space="preserve">
|
<data name="AccessibilityOverlayPermissionAlert" xml:space="preserve">
|
||||||
<value>Bitwarden needs attention - See "Auto-fill Accessibility Service" from Bitwarden Settings</value>
|
<value>Bitwarden needs attention - See "Auto-fill Accessibility Service" from Bitwarden settings</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BitwardenAutofillServiceOverlayPermission" xml:space="preserve">
|
<data name="BitwardenAutofillServiceOverlayPermission" xml:space="preserve">
|
||||||
<value>3. On the Android App Settings screen for Bitwarden, go to the "Display over other apps" options (under Advanced) and tap the toggle to enable overlay support.</value>
|
<value>3. On the Android App Settings screen for Bitwarden, go to the "Display over other apps" options (under Advanced) and tap the toggle to allow overlay support.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OverlayPermission" xml:space="preserve">
|
<data name="OverlayPermission" xml:space="preserve">
|
||||||
<value>Permission</value>
|
<value>Permission</value>
|
||||||
@@ -1659,7 +1662,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Send a verification code to your email</value>
|
<value>Send a verification code to your email</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CodeSent" xml:space="preserve">
|
<data name="CodeSent" xml:space="preserve">
|
||||||
<value>Code Sent!</value>
|
<value>Code sent!</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ConfirmYourIdentity" xml:space="preserve">
|
<data name="ConfirmYourIdentity" xml:space="preserve">
|
||||||
<value>Confirm your identity to continue.</value>
|
<value>Confirm your identity to continue.</value>
|
||||||
@@ -1674,7 +1677,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account.</value>
|
<value>Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExportVaultConfirmationTitle" xml:space="preserve">
|
<data name="ExportVaultConfirmationTitle" xml:space="preserve">
|
||||||
<value>Confirm Vault Export</value>
|
<value>Confirm vault export</value>
|
||||||
<comment>Title for the alert to confirm vault exports.</comment>
|
<comment>Title for the alert to confirm vault exports.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Warning" xml:space="preserve">
|
<data name="Warning" xml:space="preserve">
|
||||||
@@ -1704,7 +1707,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Attachment saved successfully</value>
|
<value>Attachment saved successfully</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillTileAccessibilityRequired" xml:space="preserve">
|
<data name="AutofillTileAccessibilityRequired" xml:space="preserve">
|
||||||
<value>Please enable "Auto-fill accessibility service" from Bitwarden settings to use the auto-fill tile.</value>
|
<value>Please turn on "Auto-fill Accessibility Service" from Bitwarden Settings to use the Auto-fill tile.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillTileUriNotFound" xml:space="preserve">
|
<data name="AutofillTileUriNotFound" xml:space="preserve">
|
||||||
<value>No password fields detected</value>
|
<value>No password fields detected</value>
|
||||||
@@ -1726,7 +1729,7 @@ Scanning will happen automatically.</value>
|
|||||||
<comment>Message shown when interacting with the server</comment>
|
<comment>Message shown when interacting with the server</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ItemRestored" xml:space="preserve">
|
<data name="ItemRestored" xml:space="preserve">
|
||||||
<value>Item has been restored.</value>
|
<value>Item restored</value>
|
||||||
<comment>Confirmation message after successfully restoring a soft-deleted item</comment>
|
<comment>Confirmation message after successfully restoring a soft-deleted item</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Trash" xml:space="preserve">
|
<data name="Trash" xml:space="preserve">
|
||||||
@@ -1756,7 +1759,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Biometric unlock for autofill disabled pending verification of master password.</value>
|
<value>Biometric unlock for autofill disabled pending verification of master password.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnableSyncOnRefresh" xml:space="preserve">
|
<data name="EnableSyncOnRefresh" xml:space="preserve">
|
||||||
<value>Enable sync on refresh</value>
|
<value>Allow sync on refresh</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnableSyncOnRefreshDescription" xml:space="preserve">
|
<data name="EnableSyncOnRefreshDescription" xml:space="preserve">
|
||||||
<value>Syncing vault with pull down gesture.</value>
|
<value>Syncing vault with pull down gesture.</value>
|
||||||
@@ -1822,8 +1825,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Privacy policy</value>
|
<value>Privacy policy</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccessibilityDrawOverPermissionAlert" xml:space="preserve">
|
<data name="AccessibilityDrawOverPermissionAlert" xml:space="preserve">
|
||||||
<value>Bitwarden needs attention - Enable "Draw-Over" in "Auto-fill Services" from Bitwarden Settings
|
<value>Bitwarden needs attention - Turn on "Draw-Over" in "Auto-fill Services" from Bitwarden Settings</value>
|
||||||
</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillServices" xml:space="preserve">
|
<data name="AutofillServices" xml:space="preserve">
|
||||||
<value>Auto-fill services</value>
|
<value>Auto-fill services</value>
|
||||||
@@ -1832,45 +1834,37 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Use inline autofill</value>
|
<value>Use inline autofill</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="InlineAutofillDescription" xml:space="preserve">
|
<data name="InlineAutofillDescription" xml:space="preserve">
|
||||||
<value>Use inline autofill if your selected IME (keyboard) supports it. If your configuration is not supported (or this option is disabled), the default Autofill overlay will be used.
|
<value>Use inline autofill if your selected IME (keyboard) supports it. If your configuration is not supported (or this option is turned off), the default Autofill overlay will be used.</value>
|
||||||
</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="Accessibility" xml:space="preserve">
|
<data name="Accessibility" xml:space="preserve">
|
||||||
<value>Use accessibility</value>
|
<value>Use accessibility</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccessibilityDescription" xml:space="preserve">
|
<data name="AccessibilityDescription" xml:space="preserve">
|
||||||
<value>Use the Bitwarden Accessibility Service to auto-fill your logins across apps and the web. When enabled, we'll display a popup when login fields are selected.
|
<value>Use the Bitwarden Accessibility Service to auto-fill your logins across apps and the web. When set up, we'll display a popup when login fields are selected.</value>
|
||||||
</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="AccessibilityDescription2" xml:space="preserve">
|
<data name="AccessibilityDescription2" xml:space="preserve">
|
||||||
<value>Use the Bitwarden Accessibility Service to auto-fill your logins across apps and the web. (Requires Draw-Over to be enabled as well)
|
<value>Use the Bitwarden Accessibility Service to auto-fill your logins across apps and the web. (Requires Draw-Over to be turned on as well)</value>
|
||||||
</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="AccessibilityDescription3" xml:space="preserve">
|
<data name="AccessibilityDescription3" xml:space="preserve">
|
||||||
<value>Use the Bitwarden Accessibility Service to use the Autofill Quick-Action Tile, and/or show a popup using Draw-Over (if enabled).
|
<value>Use the Bitwarden Accessibility Service to use the Autofill Quick-Action Tile, and/or show a popup using Draw-Over (if turned on).</value>
|
||||||
</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="AccessibilityDescription4" xml:space="preserve">
|
<data name="AccessibilityDescription4" xml:space="preserve">
|
||||||
<value>Required to use the Autofill Quick-Action Tile, or to augment the Autofill Service by using Draw-Over (if enabled).
|
<value>Required to use the Autofill Quick-Action Tile, or to augment the Autofill Service by using Draw-Over (if turned on).</value>
|
||||||
</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="DrawOver" xml:space="preserve">
|
<data name="DrawOver" xml:space="preserve">
|
||||||
<value>Use draw-over</value>
|
<value>Use draw-over</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DrawOverDescription" xml:space="preserve">
|
<data name="DrawOverDescription" xml:space="preserve">
|
||||||
<value>When enabled, allows the Bitwarden Accessibility Service to display a popup when login fields are selected.
|
<value>Allows the Bitwarden Accessibility Service to display a popup when login fields are selected.</value>
|
||||||
</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="DrawOverDescription2" xml:space="preserve">
|
<data name="DrawOverDescription2" xml:space="preserve">
|
||||||
<value>If enabled, the Bitwarden Accessibility Service will display a popup when login fields are selected to assist with auto-filling your logins.
|
<value>If turned on, the Bitwarden Accessibility Service will display a popup when login fields are selected to assist with auto-filling your logins.</value>
|
||||||
</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="DrawOverDescription3" xml:space="preserve">
|
<data name="DrawOverDescription3" xml:space="preserve">
|
||||||
<value>If enabled, accessibility will show a popup to augment the Autofill Service for older apps that don't support the Android Autofill Framework.
|
<value>If turned on, accessibility will show a popup to augment the Autofill Service for older apps that don't support the Android Autofill Framework.</value>
|
||||||
</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="PersonalOwnershipSubmitError" xml:space="preserve">
|
<data name="PersonalOwnershipSubmitError" xml:space="preserve">
|
||||||
<value>Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organisation and choose from available Collections.</value>
|
<value>Due to an enterprise policy, you are restricted from saving items to your individual vault. Change the ownership option to an organisation and choose from available collections.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PersonalOwnershipPolicyInEffect" xml:space="preserve">
|
<data name="PersonalOwnershipPolicyInEffect" xml:space="preserve">
|
||||||
<value>An organisation policy is affecting your ownership options.</value>
|
<value>An organisation policy is affecting your ownership options.</value>
|
||||||
@@ -1923,10 +1917,10 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Text type is not selected, tap to select.</value>
|
<value>Text type is not selected, tap to select.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DeletionDate" xml:space="preserve">
|
<data name="DeletionDate" xml:space="preserve">
|
||||||
<value>Deletion Date</value>
|
<value>Deletion date</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DeletionTime" xml:space="preserve">
|
<data name="DeletionTime" xml:space="preserve">
|
||||||
<value>Deletion Time</value>
|
<value>Deletion time</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DeletionDateInfo" xml:space="preserve">
|
<data name="DeletionDateInfo" xml:space="preserve">
|
||||||
<value>The Send will be permanently deleted on the specified date and time.</value>
|
<value>The Send will be permanently deleted on the specified date and time.</value>
|
||||||
@@ -1936,10 +1930,10 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Pending deletion</value>
|
<value>Pending deletion</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExpirationDate" xml:space="preserve">
|
<data name="ExpirationDate" xml:space="preserve">
|
||||||
<value>Expiration Date</value>
|
<value>Expiration date</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExpirationTime" xml:space="preserve">
|
<data name="ExpirationTime" xml:space="preserve">
|
||||||
<value>Expiration Time</value>
|
<value>Expiration time</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExpirationDateInfo" xml:space="preserve">
|
<data name="ExpirationDateInfo" xml:space="preserve">
|
||||||
<value>If set, access to this Send will expire on the specified date and time.</value>
|
<value>If set, access to this Send will expire on the specified date and time.</value>
|
||||||
@@ -1949,7 +1943,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Expired</value>
|
<value>Expired</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MaximumAccessCount" xml:space="preserve">
|
<data name="MaximumAccessCount" xml:space="preserve">
|
||||||
<value>Maximum Access Count</value>
|
<value>Maximum access count</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MaximumAccessCountInfo" xml:space="preserve">
|
<data name="MaximumAccessCountInfo" xml:space="preserve">
|
||||||
<value>If set, users will no longer be able to access this send once the maximum access count is reached.</value>
|
<value>If set, users will no longer be able to access this send once the maximum access count is reached.</value>
|
||||||
@@ -1959,17 +1953,17 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Max access count reached</value>
|
<value>Max access count reached</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CurrentAccessCount" xml:space="preserve">
|
<data name="CurrentAccessCount" xml:space="preserve">
|
||||||
<value>Current Access Count</value>
|
<value>Current access count</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NewPassword" xml:space="preserve">
|
<data name="NewPassword" xml:space="preserve">
|
||||||
<value>New Password</value>
|
<value>New password</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PasswordInfo" xml:space="preserve">
|
<data name="PasswordInfo" xml:space="preserve">
|
||||||
<value>Optionally require a password for users to access this Send.</value>
|
<value>Optionally require a password for users to access this Send.</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemovePassword" xml:space="preserve">
|
<data name="RemovePassword" xml:space="preserve">
|
||||||
<value>Remove Password</value>
|
<value>Remove password</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AreYouSureRemoveSendPassword" xml:space="preserve">
|
<data name="AreYouSureRemoveSendPassword" xml:space="preserve">
|
||||||
<value>Are you sure you want to remove the password?</value>
|
<value>Are you sure you want to remove the password?</value>
|
||||||
@@ -1985,7 +1979,7 @@ Scanning will happen automatically.</value>
|
|||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="DisableSend" xml:space="preserve">
|
<data name="DisableSend" xml:space="preserve">
|
||||||
<value>Disable this Send so that no one can access it</value>
|
<value>Deactivate this Send so that no one can access it</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="NoSends" xml:space="preserve">
|
<data name="NoSends" xml:space="preserve">
|
||||||
@@ -1997,10 +1991,10 @@ Scanning will happen automatically.</value>
|
|||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="CopyLink" xml:space="preserve">
|
<data name="CopyLink" xml:space="preserve">
|
||||||
<value>Copy Link</value>
|
<value>Copy link</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ShareLink" xml:space="preserve">
|
<data name="ShareLink" xml:space="preserve">
|
||||||
<value>Share Link</value>
|
<value>Share link</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SendLink" xml:space="preserve">
|
<data name="SendLink" xml:space="preserve">
|
||||||
<value>Send link</value>
|
<value>Send link</value>
|
||||||
@@ -2015,7 +2009,7 @@ Scanning will happen automatically.</value>
|
|||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="AddSend" xml:space="preserve">
|
<data name="AddSend" xml:space="preserve">
|
||||||
<value>Add Send</value>
|
<value>New Send</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="AreYouSureDeleteSend" xml:space="preserve">
|
<data name="AreYouSureDeleteSend" xml:space="preserve">
|
||||||
@@ -2023,15 +2017,15 @@ Scanning will happen automatically.</value>
|
|||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="SendDeleted" xml:space="preserve">
|
<data name="SendDeleted" xml:space="preserve">
|
||||||
<value>Send has been deleted.</value>
|
<value>Send deleted</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="SendUpdated" xml:space="preserve">
|
<data name="SendUpdated" xml:space="preserve">
|
||||||
<value>Send updated.</value>
|
<value>Send saved</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="NewSendCreated" xml:space="preserve">
|
<data name="NewSendCreated" xml:space="preserve">
|
||||||
<value>New send created.</value>
|
<value>Send created</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="OneDay" xml:space="preserve">
|
<data name="OneDay" xml:space="preserve">
|
||||||
@@ -2089,37 +2083,37 @@ Scanning will happen automatically.</value>
|
|||||||
<value>This action is protected, to continue please re-enter your master password to verify your identity.</value>
|
<value>This action is protected, to continue please re-enter your master password to verify your identity.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CaptchaRequired" xml:space="preserve">
|
<data name="CaptchaRequired" xml:space="preserve">
|
||||||
<value>Captcha Required</value>
|
<value>Captcha required</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CaptchaFailed" xml:space="preserve">
|
<data name="CaptchaFailed" xml:space="preserve">
|
||||||
<value>Captcha Failed. Please try again.</value>
|
<value>Captcha failed. Please try again.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UpdatedMasterPassword" xml:space="preserve">
|
<data name="UpdatedMasterPassword" xml:space="preserve">
|
||||||
<value>Updated Master Password</value>
|
<value>Updated master password</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UpdateMasterPassword" xml:space="preserve">
|
<data name="UpdateMasterPassword" xml:space="preserve">
|
||||||
<value>Update Master Password</value>
|
<value>Update master password</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UpdateMasterPasswordWarning" xml:space="preserve">
|
<data name="UpdateMasterPasswordWarning" xml:space="preserve">
|
||||||
<value>Your Master Password was recently changed by an administrator in your organisation. In order to access the vault, you must update your Master Password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour.</value>
|
<value>Your master password was recently changed by an administrator in your organisation. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UpdatingPassword" xml:space="preserve">
|
<data name="UpdatingPassword" xml:space="preserve">
|
||||||
<value>Updating Password</value>
|
<value>Updating password</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UpdatePasswordError" xml:space="preserve">
|
<data name="UpdatePasswordError" xml:space="preserve">
|
||||||
<value>Currently unable to update password</value>
|
<value>Currently unable to update password</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemoveMasterPassword" xml:space="preserve">
|
<data name="RemoveMasterPassword" xml:space="preserve">
|
||||||
<value>Remove Master Password</value>
|
<value>Remove master password</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemoveMasterPasswordWarning" xml:space="preserve">
|
<data name="RemoveMasterPasswordWarning" xml:space="preserve">
|
||||||
<value>{0} is using SSO with customer-managed encryption. Continuing will remove your Master Password from your account and require SSO to login.</value>
|
<value>{0} is using SSO with customer-managed encryption. Continuing will remove your master password from your account and require SSO to login.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemoveMasterPasswordWarning2" xml:space="preserve">
|
<data name="RemoveMasterPasswordWarning2" xml:space="preserve">
|
||||||
<value>If you do not want to remove your Master Password, you may leave this organisation.</value>
|
<value>If you do not want to remove your master password, you may leave this organisation.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LeaveOrganization" xml:space="preserve">
|
<data name="LeaveOrganization" xml:space="preserve">
|
||||||
<value>Leave Organisation</value>
|
<value>Leave organisation</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LeaveOrganizationName" xml:space="preserve">
|
<data name="LeaveOrganizationName" xml:space="preserve">
|
||||||
<value>Leave {0}?</value>
|
<value>Leave {0}?</value>
|
||||||
@@ -2128,7 +2122,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>FIDO2 WebAuthn</value>
|
<value>FIDO2 WebAuthn</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Fido2Instruction" xml:space="preserve">
|
<data name="Fido2Instruction" xml:space="preserve">
|
||||||
<value>To continue, have your FIDO2 WebAuthn enabled security key ready, then follow the instructions after clicking 'Authenticate WebAuthn' on the next screen.</value>
|
<value>To continue, have your FIDO2 WebAuthn compatible security key ready, then follow the instructions after clicking 'Authenticate WebAuthn' on the next screen.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Fido2Desc" xml:space="preserve">
|
<data name="Fido2Desc" xml:space="preserve">
|
||||||
<value>Authentication using FIDO2 WebAuthn, you can authenticate using an external security key.</value>
|
<value>Authentication using FIDO2 WebAuthn, you can authenticate using an external security key.</value>
|
||||||
@@ -2137,7 +2131,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Authenticate WebAuthn</value>
|
<value>Authenticate WebAuthn</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Fido2ReturnToApp" xml:space="preserve">
|
<data name="Fido2ReturnToApp" xml:space="preserve">
|
||||||
<value>Return to App</value>
|
<value>Return to app</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Fido2CheckBrowser" xml:space="preserve">
|
<data name="Fido2CheckBrowser" xml:space="preserve">
|
||||||
<value>Please make sure your default browser supports WebAuthn and try again.</value>
|
<value>Please make sure your default browser supports WebAuthn and try again.</value>
|
||||||
@@ -2146,16 +2140,16 @@ Scanning will happen automatically.</value>
|
|||||||
<value>This organisation has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organisation administrators to change your master password.</value>
|
<value>This organisation has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organisation administrators to change your master password.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="VaultTimeoutPolicyInEffect" xml:space="preserve">
|
<data name="VaultTimeoutPolicyInEffect" xml:space="preserve">
|
||||||
<value>Your organisation policies are affecting your vault timeout. Maximum allowed Vault Timeout is {0} hour(s) and {1} minute(s)</value>
|
<value>Your organisation policies are affecting your vault timeout. Maximum allowed vault timeout is {0} hour(s) and {1} minute(s)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="VaultTimeoutToLarge" xml:space="preserve">
|
<data name="VaultTimeoutToLarge" xml:space="preserve">
|
||||||
<value>Your vault timeout exceeds the restrictions set by your organisation.</value>
|
<value>Your vault timeout exceeds the restrictions set by your organisation.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DisablePersonalVaultExportPolicyInEffect">
|
<data name="DisablePersonalVaultExportPolicyInEffect">
|
||||||
<value>One or more organisation policies prevents your from exporting your personal vault.</value>
|
<value>One or more organisation policies prevents your from exporting your individual vault.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AddAccount" xml:space="preserve">
|
<data name="AddAccount" xml:space="preserve">
|
||||||
<value>Add Account</value>
|
<value>Add account</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccountUnlocked" xml:space="preserve">
|
<data name="AccountUnlocked" xml:space="preserve">
|
||||||
<value>Unlocked</value>
|
<value>Unlocked</value>
|
||||||
@@ -2164,13 +2158,13 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Locked</value>
|
<value>Locked</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccountLoggedOut" xml:space="preserve">
|
<data name="AccountLoggedOut" xml:space="preserve">
|
||||||
<value>Logged Out</value>
|
<value>Logged out</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccountSwitchedAutomatically" xml:space="preserve">
|
<data name="AccountSwitchedAutomatically" xml:space="preserve">
|
||||||
<value>Switched to next available account</value>
|
<value>Switched to next available account</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccountLockedSuccessfully" xml:space="preserve">
|
<data name="AccountLockedSuccessfully" xml:space="preserve">
|
||||||
<value>Account Locked</value>
|
<value>Account locked</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
|
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
|
||||||
<value>Account logged out successfully</value>
|
<value>Account logged out successfully</value>
|
||||||
@@ -2194,13 +2188,13 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Your account has been permanently deleted</value>
|
<value>Your account has been permanently deleted</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="InvalidVerificationCode" xml:space="preserve">
|
<data name="InvalidVerificationCode" xml:space="preserve">
|
||||||
<value>Invalid Verification Code.</value>
|
<value>Invalid verification code</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RequestOTP" xml:space="preserve">
|
<data name="RequestOTP" xml:space="preserve">
|
||||||
<value>Request one-time password</value>
|
<value>Request one-time password</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SendCode" xml:space="preserve">
|
<data name="SendCode" xml:space="preserve">
|
||||||
<value>Send Code</value>
|
<value>Send code</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Sending" xml:space="preserve">
|
<data name="Sending" xml:space="preserve">
|
||||||
<value>Sending</value>
|
<value>Sending</value>
|
||||||
@@ -2215,7 +2209,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Verifying</value>
|
<value>Verifying</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ResendCode" xml:space="preserve">
|
<data name="ResendCode" xml:space="preserve">
|
||||||
<value>Resend Code</value>
|
<value>Resend code</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AVerificationCodeWasSentToYourEmail" xml:space="preserve">
|
<data name="AVerificationCodeWasSentToYourEmail" xml:space="preserve">
|
||||||
<value>A verification code was sent to your email</value>
|
<value>A verification code was sent to your email</value>
|
||||||
@@ -2248,7 +2242,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Numbers (0 to 9)</value>
|
<value>Numbers (0 to 9)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SpecialCharacters" xml:space="preserve">
|
<data name="SpecialCharacters" xml:space="preserve">
|
||||||
<value>Special Characters (!@#$%^&*)</value>
|
<value>Special characters (!@#$%^&*)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TapToGoBack" xml:space="preserve">
|
<data name="TapToGoBack" xml:space="preserve">
|
||||||
<value>Tap to go back</value>
|
<value>Tap to go back</value>
|
||||||
@@ -2263,7 +2257,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Filter items by vault</value>
|
<value>Filter items by vault</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AllVaults" xml:space="preserve">
|
<data name="AllVaults" xml:space="preserve">
|
||||||
<value>All Vaults</value>
|
<value>All vaults</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Vaults" xml:space="preserve">
|
<data name="Vaults" xml:space="preserve">
|
||||||
<value>Vaults</value>
|
<value>Vaults</value>
|
||||||
@@ -2278,7 +2272,7 @@ Scanning will happen automatically.</value>
|
|||||||
<value>TOTP</value>
|
<value>TOTP</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerificationCodes" xml:space="preserve">
|
<data name="VerificationCodes" xml:space="preserve">
|
||||||
<value>Verification Codes</value>
|
<value>Verification codes</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PremiumSubscriptionRequired" xml:space="preserve">
|
<data name="PremiumSubscriptionRequired" xml:space="preserve">
|
||||||
<value>Premium subscription required</value>
|
<value>Premium subscription required</value>
|
||||||
@@ -2293,10 +2287,10 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Cannot scan QR Code? </value>
|
<value>Cannot scan QR Code? </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AuthenticatorKeyScanner" xml:space="preserve">
|
<data name="AuthenticatorKeyScanner" xml:space="preserve">
|
||||||
<value>Authenticator Key</value>
|
<value>Authenticator key</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnterKeyManually" xml:space="preserve">
|
<data name="EnterKeyManually" xml:space="preserve">
|
||||||
<value>Enter Key Manually</value>
|
<value>Enter key manually</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AddTotp" xml:space="preserve">
|
<data name="AddTotp" xml:space="preserve">
|
||||||
<value>Add TOTP</value>
|
<value>Add TOTP</value>
|
||||||
@@ -2308,9 +2302,6 @@ Scanning will happen automatically.</value>
|
|||||||
<value>Once the key is successfully entered,
|
<value>Once the key is successfully entered,
|
||||||
select Add TOTP to store the key safely</value>
|
select Add TOTP to store the key safely</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
|
|
||||||
<value></value>
|
|
||||||
</data>
|
|
||||||
<data name="NeverLockWarning" xml:space="preserve">
|
<data name="NeverLockWarning" xml:space="preserve">
|
||||||
<value>Setting your lock options to “Never” keeps your vault available to anyone with access to your device. If you use this option, you should ensure that you keep your device properly protected.</value>
|
<value>Setting your lock options to “Never” keeps your vault available to anyone with access to your device. If you use this option, you should ensure that you keep your device properly protected.</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2324,7 +2315,7 @@ select Add TOTP to store the key safely</value>
|
|||||||
<value>Allow screen capture</value>
|
<value>Allow screen capture</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AreYouSureYouWantToEnableScreenCapture" xml:space="preserve">
|
<data name="AreYouSureYouWantToEnableScreenCapture" xml:space="preserve">
|
||||||
<value>Are you sure you want to enable Screen Capture?</value>
|
<value>Are you sure you want to turn on screen capture?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInRequested" xml:space="preserve">
|
<data name="LogInRequested" xml:space="preserve">
|
||||||
<value>Login requested</value>
|
<value>Login requested</value>
|
||||||
@@ -2387,34 +2378,34 @@ select Add TOTP to store the key safely</value>
|
|||||||
<value>All notifications</value>
|
<value>All notifications</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PasswordType" xml:space="preserve">
|
<data name="PasswordType" xml:space="preserve">
|
||||||
<value>Password Type</value>
|
<value>Password type</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="WhatWouldYouLikeToGenerate" xml:space="preserve">
|
<data name="WhatWouldYouLikeToGenerate" xml:space="preserve">
|
||||||
<value>What would you like to generate?</value>
|
<value>What would you like to generate?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UsernameType" xml:space="preserve">
|
<data name="UsernameType" xml:space="preserve">
|
||||||
<value>Username Type</value>
|
<value>Username type</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PlusAddressedEmail" xml:space="preserve">
|
<data name="PlusAddressedEmail" xml:space="preserve">
|
||||||
<value>Plus Addressed Email</value>
|
<value>Plus addressed email</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CatchAllEmail" xml:space="preserve">
|
<data name="CatchAllEmail" xml:space="preserve">
|
||||||
<value>Catch-all Email</value>
|
<value>Catch-all email</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ForwardedEmailAlias" xml:space="preserve">
|
<data name="ForwardedEmailAlias" xml:space="preserve">
|
||||||
<value>Forwarded Email Alias</value>
|
<value>Forwarded email alias</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RandomWord" xml:space="preserve">
|
<data name="RandomWord" xml:space="preserve">
|
||||||
<value>Random Word</value>
|
<value>Random word</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EmailRequiredParenthesis" xml:space="preserve">
|
<data name="EmailRequiredParenthesis" xml:space="preserve">
|
||||||
<value>Email (required)</value>
|
<value>Email (required)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DomainNameRequiredParenthesis" xml:space="preserve">
|
<data name="DomainNameRequiredParenthesis" xml:space="preserve">
|
||||||
<value>Domain Name (required)</value>
|
<value>Domain name (required)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="APIKeyRequiredParenthesis" xml:space="preserve">
|
<data name="APIKeyRequiredParenthesis" xml:space="preserve">
|
||||||
<value>API Key (required)</value>
|
<value>API key (required)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Service" xml:space="preserve">
|
<data name="Service" xml:space="preserve">
|
||||||
<value>Service</value>
|
<value>Service</value>
|
||||||
@@ -2431,14 +2422,22 @@ select Add TOTP to store the key safely</value>
|
|||||||
<value>SimpleLogin</value>
|
<value>SimpleLogin</value>
|
||||||
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
<comment>"SimpleLogin" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="DuckDuckGo" xml:space="preserve">
|
||||||
|
<value>DuckDuckGo</value>
|
||||||
|
<comment>"DuckDuckGo" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
|
<data name="Fastmail" xml:space="preserve">
|
||||||
|
<value>Fastmail</value>
|
||||||
|
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="APIAccessToken" xml:space="preserve">
|
<data name="APIAccessToken" xml:space="preserve">
|
||||||
<value>API Access Token</value>
|
<value>API access token</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AreYouSureYouWantToOverwriteTheCurrentUsername" xml:space="preserve">
|
<data name="AreYouSureYouWantToOverwriteTheCurrentUsername" xml:space="preserve">
|
||||||
<value>Are you sure you want to overwrite the current username?</value>
|
<value>Are you sure you want to overwrite the current username?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GenerateUsername" xml:space="preserve">
|
<data name="GenerateUsername" xml:space="preserve">
|
||||||
<value>Generate Username</value>
|
<value>Generate username</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EmailType" xml:space="preserve">
|
<data name="EmailType" xml:space="preserve">
|
||||||
<value>Email Type</value>
|
<value>Email Type</value>
|
||||||
@@ -2461,6 +2460,9 @@ select Add TOTP to store the key safely</value>
|
|||||||
<data name="Random" xml:space="preserve">
|
<data name="Random" xml:space="preserve">
|
||||||
<value>Random</value>
|
<value>Random</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectToWatch" xml:space="preserve">
|
||||||
|
<value>Connect to Watch</value>
|
||||||
|
</data>
|
||||||
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
<data name="AccessibilityServiceDisclosure" xml:space="preserve">
|
||||||
<value>Accessibility Service Disclosure</value>
|
<value>Accessibility Service Disclosure</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2482,7 +2484,7 @@ select Add TOTP to store the key safely</value>
|
|||||||
Do you want to switch to this account?</value>
|
Do you want to switch to this account?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NewAroundHere" xml:space="preserve">
|
<data name="NewAroundHere" xml:space="preserve">
|
||||||
<value>Are you new here?</value>
|
<value>New around here?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GetMasterPasswordwordHint" xml:space="preserve">
|
<data name="GetMasterPasswordwordHint" xml:space="preserve">
|
||||||
<value>Get master password hint</value>
|
<value>Get master password hint</value>
|
||||||
@@ -2520,4 +2522,58 @@ Do you want to switch to this account?</value>
|
|||||||
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
|
||||||
<value>This request is no longer valid</value>
|
<value>This request is no longer valid</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Pending login requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeclineAllRequests" xml:space="preserve">
|
||||||
|
<value>Decline all requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
|
||||||
|
<value>Are you sure you want to decline all pending login requests?</value>
|
||||||
|
</data>
|
||||||
|
<data name="RequestsDeclined" xml:space="preserve">
|
||||||
|
<value>Requests declined</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoPendingRequests" xml:space="preserve">
|
||||||
|
<value>No pending requests</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
|
||||||
|
<value>Enable camera permission to use the scanner</value>
|
||||||
|
</data>
|
||||||
|
<data name="Important" xml:space="preserve">
|
||||||
|
<value>Important</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
|
||||||
|
<value>Your master password cannot be recovered if you forget it! {0} characters minimum.</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakMasterPassword" xml:space="preserve">
|
||||||
|
<value>Weak Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
|
||||||
|
<value>Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Weak" xml:space="preserve">
|
||||||
|
<value>Weak</value>
|
||||||
|
</data>
|
||||||
|
<data name="Good" xml:space="preserve">
|
||||||
|
<value>Good</value>
|
||||||
|
</data>
|
||||||
|
<data name="Strong" xml:space="preserve">
|
||||||
|
<value>Strong</value>
|
||||||
|
</data>
|
||||||
|
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
|
||||||
|
<value>Check known data breaches for this password</value>
|
||||||
|
</data>
|
||||||
|
<data name="ExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
|
||||||
|
<value>Weak and Exposed Master Password</value>
|
||||||
|
</data>
|
||||||
|
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
|
||||||
|
<value>Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user