1
0
mirror of https://github.com/bitwarden/mobile synced 2026-01-06 18:43:43 +00:00

Merge branch 'feature/maui-migration-passkeys' into PM-5731-create-c-web-authn-authenticator-to-support-maui-apps

This commit is contained in:
Federico Maccaroni
2024-02-05 14:32:00 -03:00
163 changed files with 1975 additions and 1296 deletions

19
.github/CODEOWNERS vendored
View File

@@ -1,12 +1,21 @@
# Please sort lines alphabetically, this will ensure we don't accidentally add duplicates. # Please sort into logical groups with comment headers. Sort groups in order of specificity.
# For example, default owners should always be the first group.
# Sort lines alphabetically within these groups to avoid accidentally adding duplicates.
# #
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
# The following owners will be the default owners for everything in the repo. # Default file owners
# Unless a later match takes precedence * @bitwarden/dept-development-mobile
# @bitwarden/tech-leads
@bitwarden/dept-development-mobile # DevOps for Actions and other workflow changes
.github/workflows @bitwarden/dept-devops
# DevOps for Version Bumping
src/Android/Properties/AndroidManifest.xml
src/iOS.Autofill/Info.plist
src/iOS.Extension/Info.plist
src/iOS.ShareExtension/Info.plist
src/iOS/Info.plist
## Auth team files ## ## Auth team files ##

17
.github/renovate.json vendored
View File

@@ -2,22 +2,21 @@
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [ "extends": [
"config:base", "config:base",
"github>bitwarden/renovate-config:pin-actions",
":combinePatchMinorReleases", ":combinePatchMinorReleases",
":dependencyDashboard", ":dependencyDashboard",
":maintainLockFilesWeekly", ":maintainLockFilesWeekly",
":pinAllExceptPeerDependencies", ":pinAllExceptPeerDependencies",
":prConcurrentLimit10", ":prConcurrentLimit10",
":rebaseStalePrs", ":rebaseStalePrs",
"schedule:weekends", ":separateMajorReleases",
":separateMajorReleases" "group:monorepos",
"schedule:weekends"
], ],
"enabledManagers": ["cargo", "github-actions", "npm", "nuget"], "enabledManagers": ["github-actions", "npm", "nuget"],
"commitMessagePrefix": "[deps]:",
"commitMessageTopic": "{{depName}}",
"packageRules": [ "packageRules": [
{
"groupName": "cargo minor",
"matchManagers": ["cargo"],
"matchUpdateTypes": ["minor", "patch"]
},
{ {
"groupName": "gh minor", "groupName": "gh minor",
"matchManagers": ["github-actions"], "matchManagers": ["github-actions"],
@@ -32,6 +31,6 @@
"groupName": "nuget minor", "groupName": "nuget minor",
"matchManagers": ["nuget"], "matchManagers": ["nuget"],
"matchUpdateTypes": ["minor", "patch"] "matchUpdateTypes": ["minor", "patch"]
}, }
] ]
} }

View File

@@ -75,12 +75,12 @@ jobs:
nuget-version: 6.4.0 nuget-version: 6.4.0
- name: Set up .NET - name: Set up .NET
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0 uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
with: with:
dotnet-version: '8.0.x' dotnet-version: '8.0.x'
- name: Set up MSBuild - name: Set up MSBuild
uses: microsoft/setup-msbuild@1ff57057b5cfdc39105cd07a01d78e9b0ea0c14c # v1.3.1 uses: microsoft/setup-msbuild@ede762b26a2de8d110bb5a3db4d7e0e080c0e917 # v1.3.3
# This step might be obsolete at some point as .NET MAUI workloads # This step might be obsolete at some point as .NET MAUI workloads
# are starting to come pre-installed on the GH Actions build agents. # are starting to come pre-installed on the GH Actions build agents.
@@ -157,7 +157,7 @@ jobs:
run: dotnet test test/Core.Test/Core.Test.csproj --logger "trx;LogFileName=test-results.trx" /p:CustomConstants=UT run: dotnet test test/Core.Test/Core.Test.csproj --logger "trx;LogFileName=test-results.trx" /p:CustomConstants=UT
- name: Report test results - name: Report test results
uses: dorny/test-reporter@c9b3d0e2bd2a4e96aaf424dbaa31c46b42318226 # v1.6.0 uses: dorny/test-reporter@eaa763f6ffc21c7a37837f56cd5f9737f27fc6c8 # v1.8.0
if: always() if: always()
with: with:
name: Test Results name: Test Results
@@ -226,7 +226,7 @@ jobs:
- name: Upload Prod .aab artifact - name: Upload Prod .aab artifact
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
with: with:
name: com.x8bit.bitwarden.aab name: com.x8bit.bitwarden.aab
path: ./com.x8bit.bitwarden.aab path: ./com.x8bit.bitwarden.aab
@@ -234,7 +234,7 @@ jobs:
- name: Upload Prod .apk artifact - name: Upload Prod .apk artifact
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
with: with:
name: com.x8bit.bitwarden.apk name: com.x8bit.bitwarden.apk
path: ./com.x8bit.bitwarden.apk path: ./com.x8bit.bitwarden.apk
@@ -242,7 +242,7 @@ jobs:
- name: Upload Other .apk artifact - name: Upload Other .apk artifact
if: ${{ matrix.variant != 'prod' }} if: ${{ matrix.variant != 'prod' }}
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
with: with:
name: com.x8bit.bitwarden.${{ matrix.variant }}.apk name: com.x8bit.bitwarden.${{ matrix.variant }}.apk
path: ./com.x8bit.bitwarden.${{ matrix.variant }}.apk path: ./com.x8bit.bitwarden.${{ matrix.variant }}.apk
@@ -262,7 +262,7 @@ jobs:
- name: Upload .apk sha file for prod - name: Upload .apk sha file for prod
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
with: with:
name: bw-android-apk-sha256.txt name: bw-android-apk-sha256.txt
path: ./bw-android-apk-sha256.txt path: ./bw-android-apk-sha256.txt
@@ -270,7 +270,7 @@ jobs:
- name: Upload .apk sha file for other - name: Upload .apk sha file for other
if: ${{ matrix.variant != 'prod' }} if: ${{ matrix.variant != 'prod' }}
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
with: with:
name: bw-android-${{ matrix.variant }}-apk-sha256.txt name: bw-android-${{ matrix.variant }}-apk-sha256.txt
path: ./bw-android-${{ matrix.variant }}-apk-sha256.txt path: ./bw-android-${{ matrix.variant }}-apk-sha256.txt
@@ -310,7 +310,7 @@ jobs:
dotnet-version: '8.0.x' dotnet-version: '8.0.x'
- name: Set up MSBuild - name: Set up MSBuild
uses: microsoft/setup-msbuild@1ff57057b5cfdc39105cd07a01d78e9b0ea0c14c # v1.3.1 uses: microsoft/setup-msbuild@ede762b26a2de8d110bb5a3db4d7e0e080c0e917 # v1.3.3
# This step might be obsolete at some point as .NET MAUI workloads # This step might be obsolete at some point as .NET MAUI workloads
# are starting to come pre-installed on the GH Actions build agents. # are starting to come pre-installed on the GH Actions build agents.
@@ -366,13 +366,6 @@ jobs:
$androidManifest = $($env:GITHUB_WORKSPACE + "/${{ env.android_manifest_path }}"); $androidManifest = $($env:GITHUB_WORKSPACE + "/${{ env.android_manifest_path }}");
# Write-Output "########################################"
# Write-Output "##### Clean Android and App"
# Write-Output "########################################"
# msbuild "$($androidPath)" "/t:Clean" "/p:Configuration=FDroid"
# msbuild "$($appPath)" "/t:Clean" "/p:Configuration=FDroid"
Write-Output "########################################" Write-Output "########################################"
Write-Output "##### Backup project files" Write-Output "##### Backup project files"
Write-Output "########################################" Write-Output "########################################"
@@ -392,42 +385,6 @@ jobs:
$xml.Save($androidManifest); $xml.Save($androidManifest);
# Write-Output "########################################"
# Write-Output "##### Uninstall from App.csproj"
# Write-Output "########################################"
# $xml=New-Object XML;
# $xml.Load($appPath);
# $ns=New-Object System.Xml.XmlNamespaceManager($xml.NameTable);
# $ns.AddNamespace("ns", $xml.DocumentElement.NamespaceURI);
# $firebaseNode=$xml.SelectSingleNode(`
# "/ns:Project/ns:ItemGroup/ns:PackageReference[@Include='Xamarin.Firebase.Messaging']", $ns);
# $firebaseNode.ParentNode.RemoveChild($firebaseNode);
# $daggerNode=$xml.SelectSingleNode(`
# "/ns:Project/ns:ItemGroup/ns:PackageReference[@Include='Xamarin.Google.Dagger']", $ns);
# $daggerNode.ParentNode.RemoveChild($daggerNode);
# $safetyNetNode=$xml.SelectSingleNode(`
# "/ns:Project/ns:ItemGroup/ns:PackageReference[@Include='Xamarin.GooglePlayServices.SafetyNet']", $ns);
# $safetyNetNode.ParentNode.RemoveChild($safetyNetNode);
# $xml.Save($appPath);
# Write-Output "########################################"
# Write-Output "##### Uninstall from Core.csproj"
# Write-Output "########################################"
# $xml=New-Object XML;
# $xml.Load($corePath);
# $appCenterNode=$xml.SelectSingleNode("/Project/ItemGroup/PackageReference[@Include='Microsoft.AppCenter.Crashes']");
# $appCenterNode.ParentNode.RemoveChild($appCenterNode);
# $xml.Save($corePath);
- name: Restore packages - name: Restore packages
run: dotnet restore run: dotnet restore
@@ -465,7 +422,7 @@ jobs:
Copy-Item $signedApkPath $signedApkDestPath Copy-Item $signedApkPath $signedApkDestPath
- name: Upload F-Droid .apk artifact - name: Upload F-Droid .apk artifact
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
with: with:
name: com.x8bit.bitwarden-fdroid.apk name: com.x8bit.bitwarden-fdroid.apk
path: ./com.x8bit.bitwarden-fdroid.apk path: ./com.x8bit.bitwarden-fdroid.apk
@@ -477,7 +434,7 @@ jobs:
-t sha256 | Out-File -Encoding ASCII ./bw-fdroid-apk-sha256.txt -t sha256 | Out-File -Encoding ASCII ./bw-fdroid-apk-sha256.txt
- name: Upload F-Droid sha file - name: Upload F-Droid sha file
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
with: with:
name: bw-fdroid-apk-sha256.txt name: bw-fdroid-apk-sha256.txt
path: ./bw-fdroid-apk-sha256.txt path: ./bw-fdroid-apk-sha256.txt
@@ -495,7 +452,7 @@ jobs:
- name: Set XCode version - name: Set XCode version
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0 uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
with: with:
xcode-version: 15.0.1 xcode-version: 15.1
- name: Setup NuGet - name: Setup NuGet
uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0 uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0
@@ -525,7 +482,7 @@ jobs:
submodules: 'true' submodules: 'true'
- name: Login to Azure - CI Subscription - name: Login to Azure - CI Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.6 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
@@ -705,7 +662,7 @@ jobs:
cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH
- name: Upload App Store .ipa & dSYMs artifacts - name: Upload App Store .ipa & dSYMs artifacts
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
with: with:
name: Bitwarden iOS name: Bitwarden iOS
path: | path: |
@@ -714,7 +671,7 @@ jobs:
if-no-files-found: error if-no-files-found: error
- name: Upload .app file for Automation CI - name: Upload .app file for Automation CI
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
with: with:
name: ${{ env.app_ci_output_filename }}.app.zip name: ${{ env.app_ci_output_filename }}.app.zip
path: ./bitwarden-export/${{ env.app_ci_output_filename }}.app.zip path: ./bitwarden-export/${{ env.app_ci_output_filename }}.app.zip
@@ -799,7 +756,7 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Login to Azure - CI Subscription - name: Login to Azure - CI Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.6 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
@@ -811,7 +768,7 @@ jobs:
secrets: "crowdin-api-token" secrets: "crowdin-api-token"
- name: Upload Sources - name: Upload Sources
uses: crowdin/github-action@965d501f160af7b1f88aed4c29154b0caf1e94b9 # v1.9.0 uses: crowdin/github-action@97bef4fd3f1b853eb105bc99b8d0d563760e024c # v1.17.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
@@ -858,7 +815,7 @@ jobs:
fi fi
- name: Login to Azure - CI Subscription - name: Login to Azure - CI Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.6 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
if: failure() if: failure()
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}

View File

@@ -15,10 +15,10 @@ jobs:
_CROWDIN_PROJECT_ID: "269690" _CROWDIN_PROJECT_ID: "269690"
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- name: Login to Azure - CI Subscription - name: Login to Azure - CI Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.6 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
@@ -30,7 +30,7 @@ jobs:
secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase" secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase"
- name: Download translations - name: Download translations
uses: crowdin/github-action@965d501f160af7b1f88aed4c29154b0caf1e94b9 # v1.9.0 uses: crowdin/github-action@97bef4fd3f1b853eb105bc99b8d0d563760e024c # v1.17.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}

View File

@@ -38,7 +38,7 @@ jobs:
fi fi
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- name: Check Release Version - name: Check Release Version
id: version id: version
@@ -68,7 +68,7 @@ jobs:
- name: Download all artifacts - name: Download all artifacts
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0 uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d # v3.0.0
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
@@ -76,7 +76,7 @@ jobs:
- name: Dry Run - Download all artifacts - name: Dry Run - Download all artifacts
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0 uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d # v3.0.0
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
@@ -126,11 +126,11 @@ jobs:
if: inputs.fdroid_publish if: inputs.fdroid_publish
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- name: Download F-Droid .apk artifact - name: Download F-Droid .apk artifact
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0 uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d # v3.0.0
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
@@ -139,7 +139,7 @@ jobs:
- 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' }}
uses: dawidd6/action-download-artifact@246dbf436b23d7c49e21a7ab8204ca9ecd1fe615 # v2.27.0 uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d # v3.0.0
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
@@ -147,7 +147,7 @@ jobs:
name: com.x8bit.bitwarden-fdroid.apk name: com.x8bit.bitwarden-fdroid.apk
- name: Set up Node - name: Set up Node
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
with: with:
node-version: '16.x' node-version: '16.x'

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: 'Run stale action' - name: 'Run stale action'
uses: actions/stale@f7176fd3007623b69d27091f9b9d4ab7995f0a06 # v5.2.1 uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
with: with:
stale-issue-label: 'needs-reply' stale-issue-label: 'needs-reply'
stale-pr-label: 'needs-changes' stale-pr-label: 'needs-changes'

View File

@@ -14,7 +14,7 @@ jobs:
version_number: ${{ steps.version.outputs.new-version }} version_number: ${{ steps.version.outputs.new-version }}
steps: steps:
- name: Checkout Branch - name: Checkout Branch
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- name: Calculate bumped version - name: Calculate bumped version
id: version id: version

View File

@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Login to Azure - CI Subscription - name: Login to Azure - CI Subscription
uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with: with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
@@ -33,13 +33,22 @@ jobs:
github-pat-bitwarden-devops-bot-repo-scope" github-pat-bitwarden-devops-bot-repo-scope"
- name: Checkout Branch - name: Checkout Branch
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with: with:
ref: main ref: main
repository: bitwarden/mobile
- name: Check if RC branch exists
if: ${{ inputs.cut_rc_branch == true }}
run: |
remote_rc_branch_check=$(git ls-remote --heads origin rc | wc -l)
if [[ "${remote_rc_branch_check}" -gt 0 ]]; then
echo "Remote RC branch exists."
echo "Please delete current RC branch before running again."
exit 1
fi
- name: Import GPG key - name: Import GPG key
uses: crazy-max/ghaction-import-gpg@d6f3f49f3345e29369fe57596a3ca8f94c4d2ca7 # v5.4.0 uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0
with: with:
gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }} gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }}
passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }} passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }}
@@ -183,14 +192,22 @@ jobs:
with: with:
ref: main ref: main
- name: Check if RC branch exists - name: Verify version has been updated
env:
NEW_VERSION: ${{ inputs.version_number }}
run: | run: |
remote_rc_branch_check=$(git ls-remote --heads origin rc | wc -l) CURRENT_VERSION=$(xmllint --xpath '
if [[ "${remote_rc_branch_check}" -gt 0 ]]; then string(/manifest/@*[local-name()="versionName"
echo "Remote RC branch exists." and namespace-uri()="http://schemas.android.com/apk/res/android"])
echo "Please delete current RC branch before running again." ' src/Android/Properties/AndroidManifest.xml)
exit 1
fi # Wait for version to change.
while [[ "$NEW_VERSION" != "$CURRENT_VERSION" ]]
do
echo "Waiting for version to be updated..."
sleep 10
git pull --force
done
- name: Cut RC branch - name: Cut RC branch
run: | run: |

View File

@@ -1,6 +1,12 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<MauiVersion>8.0.4-nightly.*</MauiVersion> <MauiVersion>8.0.4-nightly.*</MauiVersion>
<ReleaseCodesignProvision>Automatic:AppStore</ReleaseCodesignProvision>
<ReleaseCodesignKey>iPhone Distribution</ReleaseCodesignKey>
<IncludeBitwardeniOSExtensions>True</IncludeBitwardeniOSExtensions>
<IncludeBitwardenWatchOSApp>True</IncludeBitwardenWatchOSApp>
<Argon2IdLoadMtouchExtraArgs>-gcc_flags "-L$(ProjectDir)../../lib/ios -largon2 -force_load $(ProjectDir)../../lib/ios/libargon2.a"</Argon2IdLoadMtouchExtraArgs>
<!-- Uncomment this when Unit Testing--> <!-- Uncomment this when Unit Testing-->
<!-- <CustomConstants>UT</CustomConstants> --> <!-- <CustomConstants>UT</CustomConstants> -->
</PropertyGroup> </PropertyGroup>

2
package-lock.json generated
View File

@@ -8,7 +8,7 @@
"name": "bitwarden-mobile", "name": "bitwarden-mobile",
"version": "0.0.0", "version": "0.0.0",
"devDependencies": { "devDependencies": {
"gh-pages": "^3.2.3" "gh-pages": "3.2.3"
} }
}, },
"node_modules/array-union": { "node_modules/array-union": {

View File

@@ -6,6 +6,6 @@
"clean:l10n": "git push origin --delete l10n_master" "clean:l10n": "git push origin --delete l10n_master"
}, },
"devDependencies": { "devDependencies": {
"gh-pages": "^3.2.3" "gh-pages": "3.2.3"
} }
} }

View File

@@ -56,18 +56,20 @@
<CodesignKey>iPhone Developer</CodesignKey> <CodesignKey>iPhone Developer</CodesignKey>
<CodesignEntitlements>Platforms\iOS\Entitlements.plist</CodesignEntitlements> <CodesignEntitlements>Platforms\iOS\Entitlements.plist</CodesignEntitlements>
<UseInterpreter>true</UseInterpreter> <UseInterpreter>true</UseInterpreter>
<!--TODO: add argon2id load when library is built with the corresponding architecture for iOS Simulator--> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(RuntimeIdentifier)'=='Debug|net8.0-ios|iossimulator-x64'">
<MtouchExtraArgs>$(Argon2IdLoadMtouchExtraArgs)</MtouchExtraArgs>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(RuntimeIdentifier)'=='Debug|net8.0-ios|ios-arm64'"> <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(RuntimeIdentifier)'=='Debug|net8.0-ios|ios-arm64'">
<MtouchExtraArgs>-gcc_flags "-L$(ProjectDir)../../lib/ios -largon2 -force_load $(ProjectDir)../../lib/ios/libargon2.a"</MtouchExtraArgs> <MtouchExtraArgs>$(Argon2IdLoadMtouchExtraArgs)</MtouchExtraArgs>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0-ios|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0-ios|AnyCPU'">
<CreatePackage>false</CreatePackage> <CreatePackage>false</CreatePackage>
<CodesignProvision>Automatic:AppStore</CodesignProvision> <CodesignProvision>$(ReleaseCodesignProvision)</CodesignProvision>
<CodesignKey>iPhone Distribution</CodesignKey> <CodesignKey>$(ReleaseCodesignKey)</CodesignKey>
<CodesignEntitlements>Platforms\iOS\Entitlements.plist</CodesignEntitlements> <CodesignEntitlements>Platforms\iOS\Entitlements.plist</CodesignEntitlements>
<UseInterpreter>true</UseInterpreter> <UseInterpreter>true</UseInterpreter>
<MtouchExtraArgs>-gcc_flags "-L$(ProjectDir)../../lib/ios -largon2 -force_load $(ProjectDir)../../lib/ios/libargon2.a"</MtouchExtraArgs> <MtouchExtraArgs>$(Argon2IdLoadMtouchExtraArgs)</MtouchExtraArgs>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'"> <ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
<!--This is needed for PCLCrypto to work correctly--> <!--This is needed for PCLCrypto to work correctly-->
@@ -209,7 +211,7 @@
</MauiImage> </MauiImage>
<MauiImage Include="Resources\yubikey.png" /> <MauiImage Include="Resources\yubikey.png" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'"> <ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios' AND '$(IncludeBitwardeniOSExtensions)' == 'True'">
<ProjectReference Include="..\iOS.Autofill\iOS.Autofill.csproj"> <ProjectReference Include="..\iOS.Autofill\iOS.Autofill.csproj">
<IsAppExtension>true</IsAppExtension> <IsAppExtension>true</IsAppExtension>
<IsWatchApp>false</IsWatchApp> <IsWatchApp>false</IsWatchApp>
@@ -223,15 +225,15 @@
<IsWatchApp>false</IsWatchApp> <IsWatchApp>false</IsWatchApp>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<PropertyGroup Condition="'$(TargetFramework)'=='net8.0-ios'"> <PropertyGroup Condition="'$(TargetFramework)'=='net8.0-ios' AND '$(IncludeBitwardenWatchOSApp)' == 'True'">
<WatchAppBuildPath Condition=" '$(Configuration)' == 'Debug' ">$(Home)/Library/Developer/Xcode/DerivedData/bitwarden-acgkbpwvmebfiofokotvoerzkqcl/Build/Products</WatchAppBuildPath> <WatchAppBuildPath Condition=" '$(Configuration)' == 'Debug' ">$(Home)/Library/Developer/Xcode/DerivedData/bitwarden-acgkbpwvmebfiofokotvoerzkqcl/Build/Products</WatchAppBuildPath>
<WatchAppBuildPath Condition=" '$(Configuration)' != 'Debug' ">$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..'))/watchOS/bitwarden.xcarchive/Products/Applications/bitwarden.app/Watch</WatchAppBuildPath> <WatchAppBuildPath Condition=" '$(Configuration)' != 'Debug' ">$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..'))/watchOS/bitwarden.xcarchive/Products/Applications/bitwarden.app/Watch</WatchAppBuildPath>
<WatchAppBundle>Bitwarden.app</WatchAppBundle> <WatchAppBundle>Bitwarden.app</WatchAppBundle>
<WatchAppConfiguration Condition="'$(RuntimeIdentifier)'!='ios-arm64'">watchsimulator</WatchAppConfiguration> <WatchAppConfiguration Condition="'$(RuntimeIdentifier)'!='ios-arm64'">watchsimulator</WatchAppConfiguration>
<WatchAppConfiguration Condition="'$(RuntimeIdentifier)'=='ios-arm64'">watchos</WatchAppConfiguration> <WatchAppConfiguration Condition="'$(RuntimeIdentifier)'=='ios-arm64'">watchos</WatchAppConfiguration>
<WatchAppBundleFullPath Condition=" '$(Configuration)' == 'Debug' ">$(WatchAppBuildPath)/$(Configuration)-$(WatchAppConfiguration)/$(WatchAppBundle)</WatchAppBundleFullPath> <WatchAppBundleFullPath Condition=" '$(Configuration)' == 'Debug' ">$(WatchAppBuildPath)/$(Configuration)-$(WatchAppConfiguration)/$(WatchAppBundle)</WatchAppBundleFullPath>
<WatchAppBundleFullPath Condition=" '$(Configuration)' != 'Debug' ">$(WatchAppBuildPath)/$(WatchAppBundle)</WatchAppBundleFullPath> <WatchAppBundleFullPath Condition=" '$(Configuration)' != 'Debug' ">$(WatchAppBuildPath)/$(WatchAppBundle)</WatchAppBundleFullPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net8.0-ios' AND Exists('$(WatchAppBundleFullPath)') "> <ItemGroup Condition="'$(TargetFramework)'=='net8.0-ios' AND Exists('$(WatchAppBundleFullPath)') ">
<_ResolvedWatchAppReferences Include="$(WatchAppBundleFullPath)" /> <_ResolvedWatchAppReferences Include="$(WatchAppBundleFullPath)" />
</ItemGroup> </ItemGroup>

View File

@@ -1,5 +1,5 @@
<?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="2024.1.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="2024.2.0" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" /> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
<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" />

View File

@@ -1,5 +1,6 @@
using AndroidX.AppCompat.View.Menu; using AndroidX.AppCompat.View.Menu;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Google.Android.Material.BottomNavigation; using Google.Android.Material.BottomNavigation;
using Microsoft.Maui.Handlers; using Microsoft.Maui.Handlers;
@@ -90,7 +91,17 @@ namespace Bit.App.Handlers
if(e.Item is MenuItemImpl item) if(e.Item is MenuItemImpl item)
{ {
System.Diagnostics.Debug.WriteLine($"Tab '{item.Title}' was reselected so we'll PopToRoot."); System.Diagnostics.Debug.WriteLine($"Tab '{item.Title}' was reselected so we'll PopToRoot.");
MainThread.BeginInvokeOnMainThread(async () => await _tabbedPage.CurrentPage.Navigation.PopToRootAsync()); MainThread.BeginInvokeOnMainThread(async () =>
{
try
{
await _tabbedPage.CurrentPage.Navigation.PopToRootAsync();
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
});
} }
} }

View File

@@ -76,7 +76,8 @@ namespace Bit.Droid
//We need to get and set the Options before calling OnCreate as that will "trigger" CreateWindow on App.xaml.cs //We need to get and set the Options before calling OnCreate as that will "trigger" CreateWindow on App.xaml.cs
_appOptions = GetOptions(); _appOptions = GetOptions();
((Bit.App.App)Microsoft.Maui.Controls.Application.Current).SetOptions(_appOptions); //This does not replace existing Options in App.xaml.cs if it exists already. It only updates properties in Options related with Autofill/CreateSend/etc..
((Bit.App.App)Microsoft.Maui.Controls.Application.Current).SetAndroidOptions(_appOptions);
base.OnCreate(savedInstanceState); base.OnCreate(savedInstanceState);

View File

@@ -158,7 +158,7 @@ namespace Bit.Droid
var autofillHandler = new AutofillHandler(stateService, messagingService, clipboardService, var autofillHandler = new AutofillHandler(stateService, messagingService, clipboardService,
platformUtilsService, new LazyResolve<IEventService>()); platformUtilsService, new LazyResolve<IEventService>());
var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService); var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService);
var cryptoService = new CryptoService(stateService, cryptoFunctionService); var cryptoService = new CryptoService(stateService, cryptoFunctionService, logger);
var biometricService = new BiometricService(stateService, cryptoService); var biometricService = new BiometricService(stateService, cryptoService);
var userPinService = new UserPinService(stateService, cryptoService); var userPinService = new UserPinService(stateService, cryptoService);
var passwordRepromptService = new MobilePasswordRepromptService(platformUtilsService, cryptoService, stateService); var passwordRepromptService = new MobilePasswordRepromptService(platformUtilsService, cryptoService, stateService);

View File

@@ -15,6 +15,7 @@ using CoreNFC;
using Foundation; using Foundation;
using Microsoft.Maui.Platform; using Microsoft.Maui.Platform;
using UIKit; using UIKit;
using UserNotifications;
using WatchConnectivity; using WatchConnectivity;
namespace Bit.iOS namespace Bit.iOS
@@ -41,73 +42,78 @@ namespace Bit.iOS
private IStateService _stateService; private IStateService _stateService;
private IEventService _eventService; private IEventService _eventService;
private LazyResolve<IDeepLinkContext> _deepLinkContext = new LazyResolve<IDeepLinkContext>(); private readonly LazyResolve<IDeepLinkContext> _deepLinkContext = new LazyResolve<IDeepLinkContext>();
public override bool FinishedLaunching(UIApplication app, NSDictionary options) public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{ {
InitApp(); try
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
_storageService = ServiceContainer.Resolve<IStorageService>("storageService");
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
_eventService = ServiceContainer.Resolve<IEventService>("eventService");
ConnectToWatchIfNeededAsync().FireAndForget();
_broadcasterService.Subscribe(nameof(AppDelegate), async (message) =>
{ {
try InitApp();
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
_storageService = ServiceContainer.Resolve<IStorageService>("storageService");
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
_eventService = ServiceContainer.Resolve<IEventService>("eventService");
ConnectToWatchIfNeededAsync().FireAndForget();
_broadcasterService.Subscribe(nameof(AppDelegate), async (message) =>
{ {
if (message.Command == "startEventTimer") try
{ {
StartEventTimer(); if (message.Command == "startEventTimer")
}
else if (message.Command == "stopEventTimer")
{
var task = StopEventTimerAsync();
}
else if (message.Command is ThemeManager.UPDATED_THEME_MESSAGE_KEY)
{
MainThread.BeginInvokeOnMainThread(() =>
{ {
iOSCoreHelpers.AppearanceAdjustments(); StartEventTimer();
});
}
else if (message.Command == "listenYubiKeyOTP")
{
iOSCoreHelpers.ListenYubiKey((bool)message.Data, _deviceActionService, _nfcSession, _nfcDelegate);
}
else if (message.Command == "unlocked")
{
var needsAutofillReplacement = await _storageService.GetAsync<bool?>(
Core.Constants.AutofillNeedsIdentityReplacementKey);
if (needsAutofillReplacement.GetValueOrDefault())
{
await ASHelpers.ReplaceAllIdentitiesAsync();
} }
} else if (message.Command == "stopEventTimer")
else if (message.Command == "showAppExtension")
{
MainThread.BeginInvokeOnMainThread(() => ShowAppExtension((ExtensionPageViewModel)message.Data));
}
else if (message.Command == "syncCompleted")
{
if (message.Data is Dictionary<string, object> data && data.ContainsKey("successfully"))
{ {
var success = data["successfully"] as bool?; var task = StopEventTimerAsync();
if (success.GetValueOrDefault() && _deviceActionService.SystemMajorVersion() >= 12) }
else if (message.Command is ThemeManager.UPDATED_THEME_MESSAGE_KEY)
{
await MainThread.InvokeOnMainThreadAsync(() =>
{
iOSCoreHelpers.AppearanceAdjustments();
});
}
else if (message.Command == "listenYubiKeyOTP" && message.Data is bool listen)
{
iOSCoreHelpers.ListenYubiKey(listen, _deviceActionService, _nfcSession, _nfcDelegate);
}
else if (message.Command == "unlocked")
{
var needsAutofillReplacement = await _storageService.GetAsync<bool?>(
Core.Constants.AutofillNeedsIdentityReplacementKey);
if (needsAutofillReplacement.GetValueOrDefault())
{ {
await ASHelpers.ReplaceAllIdentitiesAsync(); await ASHelpers.ReplaceAllIdentitiesAsync();
} }
} }
} else if (message.Command == "showAppExtension")
else if (message.Command == "addedCipher" || message.Command == "editedCipher" ||
message.Command == "restoredCipher")
{
if (_deviceActionService.SystemMajorVersion() >= 12)
{ {
await MainThread.InvokeOnMainThreadAsync(() => ShowAppExtension((ExtensionPageViewModel)message.Data));
}
else if (message.Command == "syncCompleted")
{
if (message.Data is Dictionary<string, object> data && data.TryGetValue("successfully", out var value))
{
var success = value as bool?;
if (success.GetValueOrDefault() && _deviceActionService.SystemMajorVersion() >= 12)
{
await ASHelpers.ReplaceAllIdentitiesAsync();
}
}
}
else if (message.Command == "addedCipher" || message.Command == "editedCipher" ||
message.Command == "restoredCipher")
{
if (!UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
{
return;
}
if (await ASHelpers.IdentitiesSupportIncrementalAsync()) if (await ASHelpers.IdentitiesSupportIncrementalAsync())
{ {
var cipherId = message.Data as string; var cipherId = message.Data as string;
@@ -124,11 +130,13 @@ namespace Bit.iOS
} }
await ASHelpers.ReplaceAllIdentitiesAsync(); await ASHelpers.ReplaceAllIdentitiesAsync();
} }
} else if (message.Command == "deletedCipher" || message.Command == "softDeletedCipher")
else if (message.Command == "deletedCipher" || message.Command == "softDeletedCipher")
{
if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
{ {
if (!UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
{
return;
}
if (await ASHelpers.IdentitiesSupportIncrementalAsync()) if (await ASHelpers.IdentitiesSupportIncrementalAsync())
{ {
var identity = ASHelpers.ToPasswordCredentialIdentity( var identity = ASHelpers.ToPasswordCredentialIdentity(
@@ -142,105 +150,145 @@ namespace Bit.iOS
} }
await ASHelpers.ReplaceAllIdentitiesAsync(); await ASHelpers.ReplaceAllIdentitiesAsync();
} }
} else if (message.Command == "logout" && UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
else if (message.Command == "logout")
{
if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
{ {
await ASCredentialIdentityStore.SharedStore.RemoveAllCredentialIdentitiesAsync(); await ASCredentialIdentityStore.SharedStore.RemoveAllCredentialIdentitiesAsync();
} }
} else if ((message.Command == "softDeletedCipher" || message.Command == "restoredCipher")
else if ((message.Command == "softDeletedCipher" || message.Command == "restoredCipher") && UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
&& UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
{
await ASHelpers.ReplaceAllIdentitiesAsync();
}
else if (message.Command == AppHelpers.VAULT_TIMEOUT_ACTION_CHANGED_MESSAGE_COMMAND)
{
var timeoutAction = await _stateService.GetVaultTimeoutActionAsync();
if (timeoutAction == VaultTimeoutAction.Logout && UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
{
await ASCredentialIdentityStore.SharedStore.RemoveAllCredentialIdentitiesAsync();
}
else
{ {
await ASHelpers.ReplaceAllIdentitiesAsync(); await ASHelpers.ReplaceAllIdentitiesAsync();
} }
else if (message.Command == AppHelpers.VAULT_TIMEOUT_ACTION_CHANGED_MESSAGE_COMMAND)
{
var timeoutAction = await _stateService.GetVaultTimeoutActionAsync();
if (timeoutAction == VaultTimeoutAction.Logout)
{
if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
{
await ASCredentialIdentityStore.SharedStore.RemoveAllCredentialIdentitiesAsync();
}
}
else
{
await ASHelpers.ReplaceAllIdentitiesAsync();
}
}
} }
} catch (Exception ex)
catch (Exception ex) {
{ LoggerHelper.LogEvenIfCantBeResolved(ex);
LoggerHelper.LogEvenIfCantBeResolved(ex); }
} });
});
var finishedLaunching = base.FinishedLaunching(app, options); var finishedLaunching = base.FinishedLaunching(app, options);
ThemeManager.SetTheme(Microsoft.Maui.Controls.Application.Current.Resources); ThemeManager.SetTheme(Microsoft.Maui.Controls.Application.Current.Resources);
iOSCoreHelpers.AppearanceAdjustments(); iOSCoreHelpers.AppearanceAdjustments();
return finishedLaunching; return finishedLaunching;
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
throw;
}
} }
public override void OnResignActivation(UIApplication uiApplication) public override void OnResignActivation(UIApplication uiApplication)
{ {
if (UIApplication.SharedApplication.KeyWindow is null) try
{ {
if (UIApplication.SharedApplication.KeyWindow != null)
{
var view = new UIView(UIApplication.SharedApplication.KeyWindow.Frame)
{
Tag = SPLASH_VIEW_TAG
};
var backgroundView = new UIView(UIApplication.SharedApplication.KeyWindow.Frame)
{
BackgroundColor = ThemeManager.GetResourceColor("SplashBackgroundColor").ToPlatform()
};
var logo = new UIImage(!ThemeManager.UsingLightTheme ? "logo_white.png" : "logo.png");
var frame = new CGRect(0, 0, 280, 100); //Setting image width to avoid it being larger and getting cropped on smaller devices. This harcoded size should be good even for very small devices.
var imageView = new UIImageView(frame)
{
Image = logo,
Center = new CGPoint(view.Center.X, view.Center.Y - 30),
ContentMode = UIViewContentMode.ScaleAspectFit
};
view.AddSubview(backgroundView);
view.AddSubview(imageView);
UIApplication.SharedApplication.KeyWindow.AddSubview(view);
UIApplication.SharedApplication.KeyWindow.BringSubviewToFront(view);
UIApplication.SharedApplication.KeyWindow.EndEditing(true);
}
base.OnResignActivation(uiApplication); base.OnResignActivation(uiApplication);
return;
} }
catch (Exception ex)
var view = new UIView(UIApplication.SharedApplication.KeyWindow.Frame)
{ {
Tag = SPLASH_VIEW_TAG LoggerHelper.LogEvenIfCantBeResolved(ex);
}; throw;
var backgroundView = new UIView(UIApplication.SharedApplication.KeyWindow.Frame) }
{
BackgroundColor = ThemeManager.GetResourceColor("SplashBackgroundColor").ToPlatform()
};
var logo = new UIImage(!ThemeManager.UsingLightTheme ? "logo_white.png" : "logo.png");
var frame = new CGRect(0, 0, 280, 100); //Setting image width to avoid it being larger and getting cropped on smaller devices. This harcoded size should be good even for very small devices.
var imageView = new UIImageView(frame)
{
Image = logo,
Center = new CGPoint(view.Center.X, view.Center.Y - 30),
ContentMode = UIViewContentMode.ScaleAspectFit
};
view.AddSubview(backgroundView);
view.AddSubview(imageView);
UIApplication.SharedApplication.KeyWindow.AddSubview(view);
UIApplication.SharedApplication.KeyWindow.BringSubviewToFront(view);
UIApplication.SharedApplication.KeyWindow.EndEditing(true);
base.OnResignActivation(uiApplication);
} }
public override void DidEnterBackground(UIApplication uiApplication) public override void DidEnterBackground(UIApplication uiApplication)
{ {
if (_stateService != null && _deviceActionService != null) try
{ {
_stateService.SetLastActiveTimeAsync(_deviceActionService.GetActiveTime()); if (_stateService != null && _deviceActionService != null)
} {
_stateService.SetLastActiveTimeAsync(_deviceActionService.GetActiveTime());
}
_messagingService?.Send("slept"); _messagingService?.Send("slept");
base.DidEnterBackground(uiApplication); base.DidEnterBackground(uiApplication);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
throw;
}
} }
public override void OnActivated(UIApplication uiApplication) public override async void OnActivated(UIApplication uiApplication)
{ {
base.OnActivated(uiApplication); try
UIApplication.SharedApplication.ApplicationIconBadgeNumber = 0; {
UIApplication.SharedApplication.KeyWindow? base.OnActivated(uiApplication);
.ViewWithTag(SPLASH_VIEW_TAG)?
.RemoveFromSuperview();
ThemeManager.UpdateThemeOnPagesAsync(); if (UIDevice.CurrentDevice.CheckSystemVersion(17, 0))
{
await UNUserNotificationCenter.Current.SetBadgeCountAsync(0);
}
else
{
UIApplication.SharedApplication.ApplicationIconBadgeNumber = 0;
}
UIApplication.SharedApplication.KeyWindow?
.ViewWithTag(SPLASH_VIEW_TAG)?
.RemoveFromSuperview();
ThemeManager.UpdateThemeOnPagesAsync();
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
public override void WillEnterForeground(UIApplication uiApplication) public override void WillEnterForeground(UIApplication uiApplication)
{ {
_messagingService?.Send(AppHelpers.RESUMED_MESSAGE_COMMAND); try
base.WillEnterForeground(uiApplication); {
_messagingService?.Send(AppHelpers.RESUMED_MESSAGE_COMMAND);
base.WillEnterForeground(uiApplication);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
[Export("application:openURL:sourceApplication:annotation:")] [Export("application:openURL:sourceApplication:annotation:")]
@@ -251,15 +299,30 @@ namespace Bit.iOS
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options) public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{ {
return _deepLinkContext.Value.OnNewUri(url) || base.OpenUrl(app, url, options); try
{
return _deepLinkContext.Value.OnNewUri(url) || base.OpenUrl(app, url, options);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
return false;
}
} }
public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity,
UIApplicationRestorationHandler completionHandler) UIApplicationRestorationHandler completionHandler)
{ {
if (Microsoft.Maui.ApplicationModel.Platform.ContinueUserActivity(application, userActivity, completionHandler)) try
{ {
return true; if (Microsoft.Maui.ApplicationModel.Platform.ContinueUserActivity(application, userActivity, completionHandler))
{
return true;
}
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
} }
return base.ContinueUserActivity(application, userActivity, completionHandler); return base.ContinueUserActivity(application, userActivity, completionHandler);
} }
@@ -267,33 +330,68 @@ namespace Bit.iOS
[Export("application:didFailToRegisterForRemoteNotificationsWithError:")] [Export("application:didFailToRegisterForRemoteNotificationsWithError:")]
public void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error) public void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
{ {
_pushHandler?.OnErrorReceived(error); try
{
_pushHandler?.OnErrorReceived(error);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
[Export("application:didRegisterForRemoteNotificationsWithDeviceToken:")] [Export("application:didRegisterForRemoteNotificationsWithDeviceToken:")]
public void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) public void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{ {
_pushHandler?.OnRegisteredSuccess(deviceToken); try
{
_pushHandler?.OnRegisteredSuccess(deviceToken);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
[Export("application:didRegisterUserNotificationSettings:")] [Export("application:didRegisterUserNotificationSettings:")]
public void DidRegisterUserNotificationSettings(UIApplication application, public void DidRegisterUserNotificationSettings(UIApplication application,
UIUserNotificationSettings notificationSettings) UIUserNotificationSettings notificationSettings)
{ {
application.RegisterForRemoteNotifications(); try
{
application.RegisterForRemoteNotifications();
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
[Export("application:didReceiveRemoteNotification:fetchCompletionHandler:")] [Export("application:didReceiveRemoteNotification:fetchCompletionHandler:")]
public void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, public void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo,
Action<UIBackgroundFetchResult> completionHandler) Action<UIBackgroundFetchResult> completionHandler)
{ {
_pushHandler?.OnMessageReceived(userInfo); try
{
_pushHandler?.OnMessageReceived(userInfo);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
[Export("application:didReceiveRemoteNotification:")] [Export("application:didReceiveRemoteNotification:")]
public void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo) public void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
{ {
_pushHandler?.OnMessageReceived(userInfo); try
{
_pushHandler?.OnMessageReceived(userInfo);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
public void InitApp() public void InitApp()
@@ -319,7 +417,7 @@ namespace Bit.iOS
_nfcDelegate = new Core.NFCReaderDelegate((success, message) => _nfcDelegate = new Core.NFCReaderDelegate((success, message) =>
_messagingService.Send("gotYubiKeyOTP", message)); _messagingService.Send("gotYubiKeyOTP", message));
iOSCoreHelpers.Bootstrap(async () => await ApplyManagedSettingsAsync()); iOSCoreHelpers.Bootstrap(ApplyManagedSettingsAsync);
} }
private void RegisterPush() private void RegisterPush()
@@ -364,31 +462,45 @@ namespace Bit.iOS
_eventTimer = null; _eventTimer = null;
MainThread.BeginInvokeOnMainThread(() => MainThread.BeginInvokeOnMainThread(() =>
{ {
_eventTimer = NSTimer.CreateScheduledTimer(60, true, timer => try
{ {
var task = Task.Run(() => _eventService.UploadEventsAsync()); _eventTimer = NSTimer.CreateScheduledTimer(60, true, timer =>
}); {
_eventService?.UploadEventsAsync().FireAndForget();
});
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
}); });
} }
private async Task StopEventTimerAsync() private async Task StopEventTimerAsync()
{ {
_eventTimer?.Invalidate(); try
_eventTimer?.Dispose();
_eventTimer = null;
if (_eventBackgroundTaskId > 0)
{ {
_eventTimer?.Invalidate();
_eventTimer?.Dispose();
_eventTimer = null;
if (_eventBackgroundTaskId > 0)
{
UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId);
_eventBackgroundTaskId = 0;
}
_eventBackgroundTaskId = UIApplication.SharedApplication.BeginBackgroundTask(() =>
{
UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId);
_eventBackgroundTaskId = 0;
});
await _eventService.UploadEventsAsync();
UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId); UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId);
_eventBackgroundTaskId = 0; _eventBackgroundTaskId = 0;
} }
_eventBackgroundTaskId = UIApplication.SharedApplication.BeginBackgroundTask(() => catch (Exception ex)
{ {
UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId); LoggerHelper.LogEvenIfCantBeResolved(ex);
_eventBackgroundTaskId = 0; }
});
await _eventService.UploadEventsAsync();
UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId);
_eventBackgroundTaskId = 0;
} }
private async Task ApplyManagedSettingsAsync() private async Task ApplyManagedSettingsAsync()

View File

@@ -11,7 +11,7 @@
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.8bit.bitwarden</string> <string>com.8bit.bitwarden</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2024.1.1</string> <string>2024.2.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1</string> <string>1</string>
<key>CFBundleIconName</key> <key>CFBundleIconName</key>

View File

@@ -63,5 +63,7 @@ namespace Bit.Core.Abstractions
Task<UserKey> DecryptAndMigrateOldPinKeyAsync(bool masterPasswordOnRestart, string pin, string email, KdfConfig kdfConfig, EncString oldPinKey); Task<UserKey> DecryptAndMigrateOldPinKeyAsync(bool masterPasswordOnRestart, string pin, string email, KdfConfig kdfConfig, EncString oldPinKey);
Task<MasterKey> GetOrDeriveMasterKeyAsync(string password, string userId = null); Task<MasterKey> GetOrDeriveMasterKeyAsync(string password, string userId = null);
Task UpdateMasterKeyAndUserKeyAsync(MasterKey masterKey); Task UpdateMasterKeyAndUserKeyAsync(MasterKey masterKey);
Task<string> HashAsync(string value, CryptoHashAlgorithm hashAlgorithm);
Task<bool> ValidateUriChecksumAsync(EncString remoteUriChecksum, string rawUri, string orgId, SymmetricCryptoKey key);
} }
} }

View File

@@ -81,14 +81,31 @@ namespace Bit.App
{ {
get get
{ {
return Application.Current.Windows.OfType<ResumeWindow>().FirstOrDefault(w => w.IsActive); return Application.Current?.Windows.OfType<ResumeWindow>().FirstOrDefault(w => w.IsActive);
} }
} }
//Allows setting Options from MainActivity before base.OnCreate /// <summary>
public void SetOptions(AppOptions appOptions) /// Allows setting Options from MainActivity before base.OnCreate
/// Note 1: This is only be used by Android due to way it's Lifecycle works
/// Note 2: This method does not replace existing Options in App.xaml.cs if it exists already.
/// It only updates properties in Options related with Autofill/CreateSend/etc..
/// </summary>
/// <param name="appOptions">Options created in Android MainActivity.cs</param>
public void SetAndroidOptions(AppOptions appOptions)
{ {
Options = appOptions ?? new AppOptions(); if (Options == null)
{
Options = appOptions ?? new AppOptions();
}
else if(appOptions != null)
{
Options.Uri = appOptions.Uri;
Options.MyVaultTile = appOptions.MyVaultTile;
Options.GeneratorTile = appOptions.GeneratorTile;
Options.FromAutofillFramework = appOptions.FromAutofillFramework;
Options.CreateSend = appOptions.CreateSend;
}
} }
protected override Window CreateWindow(IActivationState activationState) protected override Window CreateWindow(IActivationState activationState)
@@ -145,11 +162,14 @@ namespace Bit.App
{ {
get get
{ {
return Application.Current.MainPage; return Application.Current?.MainPage;
} }
set set
{ {
Application.Current.MainPage = value; if (Application.Current != null)
{
Application.Current.MainPage = value;
}
} }
} }
#endif #endif

View File

@@ -70,10 +70,11 @@ namespace Bit.Core
public const int Argon2Parallelism = 4; public const int Argon2Parallelism = 4;
public const int MasterPasswordMinimumChars = 12; public const int MasterPasswordMinimumChars = 12;
public const int CipherKeyRandomBytesLength = 64; public const int CipherKeyRandomBytesLength = 64;
public const string CipherKeyEncryptionMinServerVersion = "2023.9.1"; public const string CipherKeyEncryptionMinServerVersion = "2024.2.0";
public const string DefaultFido2CredentialType = "public-key"; public const string DefaultFido2CredentialType = "public-key";
public const string DefaultFido2CredentialAlgorithm = "ECDSA"; public const string DefaultFido2CredentialAlgorithm = "ECDSA";
public const string DefaultFido2CredentialCurve = "P-256"; public const string DefaultFido2CredentialCurve = "P-256";
public const int LatestStateVersion = 7;
public static readonly string[] AndroidAllClearCipherCacheKeys = public static readonly string[] AndroidAllClearCipherCacheKeys =
{ {

View File

@@ -12,12 +12,14 @@
BackgroundColor="#22000000" BackgroundColor="#22000000"
Padding="0" Padding="0"
IsVisible="False"> IsVisible="False">
<VerticalStackLayout <Grid
x:Name="_accountListContainer" x:Name="_accountListContainer"
VerticalOptions="Fill" VerticalOptions="Fill"
HorizontalOptions="FillAndExpand" HorizontalOptions="Fill"
BackgroundColor="Transparent"> BackgroundColor="Transparent"
RowDefinitions="Auto, *">
<Frame <Frame
Grid.Row="0"
Padding="0" Padding="0"
HorizontalOptions="Fill" HorizontalOptions="Fill"
VerticalOptions="Start"> VerticalOptions="Start">
@@ -49,12 +51,13 @@
</ListView> </ListView>
</Frame> </Frame>
<BoxView <BoxView
Grid.Row="1"
BackgroundColor="Transparent" BackgroundColor="Transparent"
HorizontalOptions="Fill" HorizontalOptions="Fill"
VerticalOptions="FillAndExpand"> VerticalOptions="Fill">
<BoxView.GestureRecognizers> <BoxView.GestureRecognizers>
<TapGestureRecognizer Tapped="FreeSpaceOverlay_Tapped" /> <TapGestureRecognizer Tapped="FreeSpaceOverlay_Tapped" />
</BoxView.GestureRecognizers> </BoxView.GestureRecognizers>
</BoxView> </BoxView>
</VerticalStackLayout> </Grid>
</ContentView> </ContentView>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<controls:ExtendedGrid xmlns="http://schemas.microsoft.com/dotnet/2021/maui" <controls:BaseCipherViewCell xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Bit.App.Controls.AuthenticatorViewCell" x:Class="Bit.App.Controls.AuthenticatorViewCell"
xmlns:controls="clr-namespace:Bit.App.Controls" xmlns:controls="clr-namespace:Bit.App.Controls"
@@ -13,33 +13,32 @@
RowSpacing="0" RowSpacing="0"
Padding="0,10,0,0" Padding="0,10,0,0"
RowDefinitions="*,*"> RowDefinitions="*,*">
<Grid.Resources> <controls:BaseCipherViewCell.Resources>
<u:IconGlyphConverter x:Key="iconGlyphConverter" /> <u:IconGlyphConverter x:Key="iconGlyphConverter" />
<u:InverseBoolConverter x:Key="inverseBool" /> <u:InverseBoolConverter x:Key="inverseBool" />
</Grid.Resources> </controls:BaseCipherViewCell.Resources>
<controls:IconLabel
Grid.Column="0"
HorizontalOptions="Center"
VerticalOptions="Center"
StyleClass="list-icon, list-icon-platform"
Grid.RowSpan="2"
IsVisible="{Binding ShowIconImage, Converter={StaticResource inverseBool}}"
Text="{Binding Cipher, Converter={StaticResource iconGlyphConverter}}"
AutomationProperties.IsInAccessibleTree="False" />
<controls:CachedImage <controls:CachedImage
x:Name="_iconImage"
Grid.Column="0" Grid.Column="0"
Grid.RowSpan="2"
BitmapOptimizations="True" BitmapOptimizations="True"
ErrorPlaceholder="login.png"
LoadingPlaceholder="login.png"
HorizontalOptions="Center" HorizontalOptions="Center"
VerticalOptions="Center" VerticalOptions="Center"
WidthRequest="22" WidthRequest="22"
HeightRequest="22" HeightRequest="22"
Success="Icon_Success"
Error="Icon_Error"
AutomationProperties.IsInAccessibleTree="False" />
<controls:IconLabel
x:Name="_iconPlaceholderImage"
Grid.Column="0"
Grid.RowSpan="2" Grid.RowSpan="2"
IsVisible="{Binding ShowIconImage}" HorizontalOptions="Center"
Source="{Binding IconImageSource, Mode=OneTime}" VerticalOptions="Center"
StyleClass="list-icon, list-icon-platform"
Text="{Binding Cipher, Converter={StaticResource iconGlyphConverter}}"
AutomationProperties.IsInAccessibleTree="False" /> AutomationProperties.IsInAccessibleTree="False" />
<Label <Label
@@ -47,7 +46,7 @@
Grid.Column="1" Grid.Column="1"
Grid.Row="0" Grid.Row="0"
VerticalTextAlignment="Center" VerticalTextAlignment="Center"
VerticalOptions="Fill" VerticalOptions="End"
StyleClass="list-title, list-title-platform" StyleClass="list-title, list-title-platform"
Text="{Binding Cipher.Name}" /> Text="{Binding Cipher.Name}" />
@@ -56,7 +55,7 @@
Grid.Column="1" Grid.Column="1"
Grid.Row="1" Grid.Row="1"
VerticalTextAlignment="Center" VerticalTextAlignment="Center"
VerticalOptions="Fill" VerticalOptions="Start"
StyleClass="list-subtitle, list-subtitle-platform" StyleClass="list-subtitle, list-subtitle-platform"
Text="{Binding Cipher.SubTitle}" /> Text="{Binding Cipher.SubTitle}" />
@@ -66,11 +65,14 @@
Grid.Column="2" Grid.Column="2"
Grid.RowSpan="2" Grid.RowSpan="2"
HorizontalOptions="Fill" HorizontalOptions="Fill"
WidthRequest="50"
HeightRequest="50"
VerticalOptions="CenterAndExpand" /> VerticalOptions="CenterAndExpand" />
<Label <Label
Text="{Binding TotpSec, Mode=OneWay}" Text="{Binding TotpSec, Mode=OneWay}"
Style="{DynamicResource textTotp}" Style="{DynamicResource textTotp}"
BackgroundColor="Transparent"
Grid.Row="0" Grid.Row="0"
Grid.Column="2" Grid.Column="2"
Grid.RowSpan="2" Grid.RowSpan="2"
@@ -121,4 +123,4 @@
HorizontalOptions="Center" HorizontalOptions="Center"
VerticalOptions="Center" VerticalOptions="Center"
SemanticProperties.Description="{u:I18n CopyTotp}" /> SemanticProperties.Description="{u:I18n CopyTotp}" />
</controls:ExtendedGrid> </controls:BaseCipherViewCell>

View File

@@ -1,10 +1,14 @@
namespace Bit.App.Controls namespace Bit.App.Controls
{ {
public partial class AuthenticatorViewCell : ExtendedGrid public partial class AuthenticatorViewCell : BaseCipherViewCell
{ {
public AuthenticatorViewCell() public AuthenticatorViewCell()
{ {
InitializeComponent(); InitializeComponent();
} }
protected override CachedImage Icon => _iconImage;
protected override IconLabel IconPlaceholder => _iconPlaceholderImage;
} }
} }

View File

@@ -0,0 +1,62 @@
using SkiaSharp;
namespace Bit.App.Controls
{
public class AvatarImageSource : StreamImageSource
{
private readonly string _text;
private readonly string _id;
private readonly string _color;
private readonly AvatarInfo _avatarInfo;
public override bool Equals(object obj)
{
if (obj is null)
{
return false;
}
if (obj is AvatarImageSource avatar)
{
return avatar._id == _id && avatar._text == _text && avatar._color == _color;
}
return base.Equals(obj);
}
public override int GetHashCode() => _id?.GetHashCode() ?? _text?.GetHashCode() ?? -1;
public AvatarImageSource(string userId = null, string name = null, string email = null, string color = null)
{
_id = userId;
_text = name;
if (string.IsNullOrWhiteSpace(_text))
{
_text = email;
}
_color = color;
//Workaround: [MAUI-Migration] There is currently a bug in MAUI where the actual size of the image is used instead of the size it should occupy in the Toolbar.
//This causes some issues with the position of the icon. As a workaround we make the icon smaller until this is fixed.
//Github issues: https://github.com/dotnet/maui/issues/12359 and https://github.com/dotnet/maui/pull/17120
_avatarInfo = new AvatarInfo(userId, name, email, color, DeviceInfo.Platform == DevicePlatform.iOS ? 20 : 50);
}
public override Func<CancellationToken, Task<Stream>> Stream => GetStreamAsync;
private Task<Stream> GetStreamAsync(CancellationToken userToken = new CancellationToken())
{
var result = Draw();
return Task.FromResult(result);
}
private Stream Draw()
{
using (var img = SKAvatarImageHelper.Draw(_avatarInfo))
{
var data = img.Encode(SKEncodedImageFormat.Png, 100);
return data?.AsStream(true);
}
}
}
}

View File

@@ -0,0 +1,63 @@
using Bit.Core.Utilities;
#nullable enable
namespace Bit.App.Controls
{
public struct AvatarInfo
{
private const string DEFAULT_BACKGROUND_COLOR = "#33ffffff";
public AvatarInfo(string? userId = null, string? name = null, string? email = null, string? color = null, int size = 50)
{
Size = size;
var text = string.IsNullOrWhiteSpace(name) ? email : name;
string? upperCaseText = null;
if (string.IsNullOrEmpty(text))
{
CharsToDraw = "..";
}
else if (text.Length > 1)
{
upperCaseText = text.ToUpper();
CharsToDraw = GetFirstLetters(upperCaseText, 2);
}
else
{
CharsToDraw = upperCaseText = text.ToUpper();
}
BackgroundColor = color ?? CoreHelpers.StringToColor(userId ?? upperCaseText, DEFAULT_BACKGROUND_COLOR);
TextColor = CoreHelpers.TextColorFromBgColor(BackgroundColor);
}
public string CharsToDraw { get; }
public string BackgroundColor { get; }
public string TextColor { get; }
public int Size { get; }
private static string GetFirstLetters(string data, int charCount)
{
var sanitizedData = data.Trim();
var parts = sanitizedData.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length > 1 && charCount <= 2)
{
var text = string.Empty;
for (var i = 0; i < charCount; i++)
{
text += parts[i][0];
}
return text;
}
if (sanitizedData.Length > 2)
{
return sanitizedData.Substring(0, 2);
}
return sanitizedData;
}
}
}

View File

@@ -0,0 +1,63 @@
using SkiaSharp;
namespace Bit.App.Controls
{
public static class SKAvatarImageHelper
{
public static SKImage Draw(AvatarInfo avatarInfo)
{
using (var bitmap = new SKBitmap(avatarInfo.Size * 2,
avatarInfo.Size * 2,
SKImageInfo.PlatformColorType,
SKAlphaType.Premul))
{
using (var canvas = new SKCanvas(bitmap))
{
canvas.Clear(SKColors.Transparent);
using (var paint = new SKPaint
{
IsAntialias = true,
Style = SKPaintStyle.Fill,
StrokeJoin = SKStrokeJoin.Miter,
Color = SKColor.Parse(avatarInfo.BackgroundColor)
})
{
var midX = canvas.LocalClipBounds.Size.ToSizeI().Width / 2;
var midY = canvas.LocalClipBounds.Size.ToSizeI().Height / 2;
var radius = midX - midX / 5;
using (var circlePaint = new SKPaint
{
IsAntialias = true,
Style = SKPaintStyle.Fill,
StrokeJoin = SKStrokeJoin.Miter,
Color = SKColor.Parse(avatarInfo.BackgroundColor)
})
{
canvas.DrawCircle(midX, midY, radius, circlePaint);
var typeface = SKTypeface.FromFamilyName("Arial", SKFontStyle.Normal);
var textSize = midX / 1.3f;
using (var textPaint = new SKPaint
{
IsAntialias = true,
Style = SKPaintStyle.Fill,
Color = SKColor.Parse(avatarInfo.TextColor),
TextSize = textSize,
TextAlign = SKTextAlign.Center,
Typeface = typeface
})
{
var rect = new SKRect();
textPaint.MeasureText(avatarInfo.CharsToDraw, ref rect);
canvas.DrawText(avatarInfo.CharsToDraw, midX, midY + rect.Height / 2, textPaint);
return SKImage.FromBitmap(bitmap);
}
}
}
}
}
}
}
}

View File

@@ -1,179 +0,0 @@
using Bit.Core.Utilities;
using SkiaSharp;
namespace Bit.App.Controls
{
public class AvatarImageSource : StreamImageSource
{
private readonly string _text;
private readonly string _id;
private readonly string _color;
public override bool Equals(object obj)
{
if (obj is null)
{
return false;
}
if (obj is AvatarImageSource avatar)
{
return avatar._id == _id && avatar._text == _text && avatar._color == _color;
}
return base.Equals(obj);
}
public override int GetHashCode() => _id?.GetHashCode() ?? _text?.GetHashCode() ?? -1;
public AvatarImageSource(string userId = null, string name = null, string email = null, string color = null)
{
_id = userId;
_text = name;
if (string.IsNullOrWhiteSpace(_text))
{
_text = email;
}
_color = color;
}
public override Func<CancellationToken, Task<Stream>> Stream => GetStreamAsync;
private Task<Stream> GetStreamAsync(CancellationToken userToken = new CancellationToken())
{
var result = Draw();
return Task.FromResult(result);
}
private Stream Draw()
{
string chars;
string upperCaseText = null;
if (string.IsNullOrEmpty(_text))
{
chars = "..";
}
else if (_text?.Length > 1)
{
upperCaseText = _text.ToUpper();
chars = GetFirstLetters(upperCaseText, 2);
}
else
{
chars = upperCaseText = _text.ToUpper();
}
var bgColor = _color ?? CoreHelpers.StringToColor(_id ?? upperCaseText, "#33ffffff");
var textColor = CoreHelpers.TextColorFromBgColor(bgColor);
var size = 50;
//Workaround: [MAUI-Migration] There is currently a bug in MAUI where the actual size of the image is used instead of the size it should occupy in the Toolbar.
//This causes some issues with the position of the icon. As a workaround we make the icon smaller until this is fixed.
//Github issues: https://github.com/dotnet/maui/issues/12359 and https://github.com/dotnet/maui/pull/17120
if (DeviceInfo.Platform == DevicePlatform.iOS)
{
size = 20;
}
using (var bitmap = new SKBitmap(size * 2,
size * 2,
SKImageInfo.PlatformColorType,
SKAlphaType.Premul))
{
using (var canvas = new SKCanvas(bitmap))
{
canvas.Clear(SKColors.Transparent);
using (var paint = new SKPaint
{
IsAntialias = true,
Style = SKPaintStyle.Fill,
StrokeJoin = SKStrokeJoin.Miter,
Color = SKColor.Parse(bgColor)
})
{
var midX = canvas.LocalClipBounds.Size.ToSizeI().Width / 2;
var midY = canvas.LocalClipBounds.Size.ToSizeI().Height / 2;
var radius = midX - midX / 5;
using (var circlePaint = new SKPaint
{
IsAntialias = true,
Style = SKPaintStyle.Fill,
StrokeJoin = SKStrokeJoin.Miter,
Color = SKColor.Parse(bgColor)
})
{
canvas.DrawCircle(midX, midY, radius, circlePaint);
var typeface = SKTypeface.FromFamilyName("Arial", SKFontStyle.Normal);
var textSize = midX / 1.3f;
using (var textPaint = new SKPaint
{
IsAntialias = true,
Style = SKPaintStyle.Fill,
Color = SKColor.Parse(textColor),
TextSize = textSize,
TextAlign = SKTextAlign.Center,
Typeface = typeface
})
{
var rect = new SKRect();
textPaint.MeasureText(chars, ref rect);
canvas.DrawText(chars, midX, midY + rect.Height / 2, textPaint);
using (var img = SKImage.FromBitmap(bitmap))
{
var data = img.Encode(SKEncodedImageFormat.Png, 100);
return data?.AsStream(true);
}
}
}
}
}
}
}
private string GetFirstLetters(string data, int charCount)
{
var sanitizedData = data.Trim();
var parts = sanitizedData.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length > 1 && charCount <= 2)
{
var text = string.Empty;
for (var i = 0; i < charCount; i++)
{
text += parts[i][0];
}
return text;
}
if (sanitizedData.Length > 2)
{
return sanitizedData.Substring(0, 2);
}
return sanitizedData;
}
private Color StringToColor(string str)
{
if (str == null)
{
return Color.FromArgb("#33ffffff");
}
var hash = 0;
for (var i = 0; i < str.Length; i++)
{
hash = str[i] + ((hash << 5) - hash);
}
var color = "#FF";
for (var i = 0; i < 3; i++)
{
var value = (hash >> (i * 8)) & 0xff;
var base16 = "00" + Convert.ToString(value, 16);
color += base16.Substring(base16.Length - 2);
}
return Color.FromArgb(color);
}
}
}

View File

@@ -0,0 +1,103 @@
using Bit.App.Pages;
namespace Bit.App.Controls
{
public abstract class BaseCipherViewCell : ExtendedGrid
{
protected virtual CachedImage Icon { get; }
protected virtual IconLabel IconPlaceholder { get; }
// HACK: PM-5896 Fix for Background Crash on iOS
// While loading the cipher icon and the user sent the app to background
// the app was crashing sometimes when the "LoadingPlaceholder" or "ErrorPlaceholder"
// were being accessed, thus locked, and as soon the app got suspended by the OS
// the app would crash because there can't be any lock files by the app when it gets suspended.
// So, the approach has changed to reuse the IconLabel default icon to use it for these placeholders
// as well. In order to do that both icon controls change their visibility dynamically here reacting to
// CachedImage events and binding context changes.
protected override void OnBindingContextChanged()
{
Icon.Source = null;
if (BindingContext is CipherItemViewModel cipherItemVM)
{
Icon.Source = cipherItemVM.IconImageSource;
if (!cipherItemVM.IconImageSuccesfullyLoaded)
{
UpdateIconImages(cipherItemVM.ShowIconImage);
}
}
base.OnBindingContextChanged();
}
private void UpdateIconImages(bool showIcon)
{
MainThread.BeginInvokeOnMainThread(() =>
{
if (!showIcon)
{
Icon.IsVisible = false;
IconPlaceholder.IsVisible = true;
return;
}
IconPlaceholder.IsVisible = Icon.IsLoading;
});
}
public void Icon_Success(object sender, FFImageLoading.Maui.CachedImageEvents.SuccessEventArgs e)
{
if (BindingContext is CipherItemViewModel cipherItemVM)
{
cipherItemVM.IconImageSuccesfullyLoaded = true;
}
MainThread.BeginInvokeOnMainThread(() =>
{
Icon.IsVisible = true;
IconPlaceholder.IsVisible = false;
});
}
public void Icon_Error(object sender, FFImageLoading.Maui.CachedImageEvents.ErrorEventArgs e)
{
if (BindingContext is CipherItemViewModel cipherItemVM)
{
cipherItemVM.IconImageSuccesfullyLoaded = false;
}
MainThread.BeginInvokeOnMainThread(() =>
{
Icon.IsVisible = false;
IconPlaceholder.IsVisible = true;
});
}
}
public class StubBaseCipherViewCellSoLinkerDoesntRemoveMethods : BaseCipherViewCell
{
protected override CachedImage Icon => new CachedImage();
protected override IconLabel IconPlaceholder => new IconLabel();
public static void CallThisSoLinkerDoesntRemoveMethods()
{
var stub = new StubBaseCipherViewCellSoLinkerDoesntRemoveMethods();
try
{
stub.Icon_Success(stub, new FFImageLoading.Maui.CachedImageEvents.SuccessEventArgs(new FFImageLoading.Work.ImageInformation(), FFImageLoading.Work.LoadingResult.Disk));
}
catch (Exception)
{
}
try
{
stub.Icon_Error(stub, new FFImageLoading.Maui.CachedImageEvents.ErrorEventArgs(new InvalidOperationException("stub")));
}
catch (Exception)
{
}
}
}
}

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<controls:ExtendedGrid xmlns="http://schemas.microsoft.com/dotnet/2021/maui" <controls:BaseCipherViewCell xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Bit.App.Controls.CipherViewCell" x:Class="Bit.App.Controls.CipherViewCell"
xmlns:controls="clr-namespace:Bit.App.Controls" xmlns:controls="clr-namespace:Bit.App.Controls"
@@ -29,34 +29,32 @@
<ColumnDefinition Width="60" /> <ColumnDefinition Width="60" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<controls:IconLabel
Grid.Column="0"
HorizontalOptions="Center"
VerticalOptions="Center"
StyleClass="list-icon, list-icon-platform"
IsVisible="{Binding ShowIconImage, Converter={StaticResource inverseBool}}"
Text="{Binding Cipher, Converter={StaticResource iconGlyphConverter}}"
ShouldUpdateFontSizeDynamicallyForAccesibility="True"
AutomationProperties.IsInAccessibleTree="False"
AutomationId="CipherTypeIcon" />
<controls:CachedImage <controls:CachedImage
x:Name="_iconImage" x:Name="_iconImage"
Grid.Column="0" Grid.Column="0"
BitmapOptimizations="True" BitmapOptimizations="True"
ErrorPlaceholder="login.png"
LoadingPlaceholder="login.png"
HorizontalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"
Margin="9" Margin="9"
WidthRequest="22" WidthRequest="22"
HeightRequest="22" HeightRequest="22"
Aspect="AspectFit" Aspect="AspectFit"
IsVisible="{Binding ShowIconImage}" Success="Icon_Success"
Source="{Binding IconImageSource, Mode=OneTime}" Error="Icon_Error"
AutomationProperties.IsInAccessibleTree="False" AutomationProperties.IsInAccessibleTree="False"
AutomationId="CipherWebsiteIcon" /> AutomationId="CipherWebsiteIcon" />
<controls:IconLabel
x:Name="_iconPlaceholderImage"
Grid.Column="0"
HorizontalOptions="Center"
VerticalOptions="Center"
StyleClass="list-icon, list-icon-platform"
Text="{Binding Cipher, Converter={StaticResource iconGlyphConverter}}"
ShouldUpdateFontSizeDynamicallyForAccesibility="True"
AutomationProperties.IsInAccessibleTree="False"
AutomationId="CipherTypeIcon" />
<Grid RowSpacing="0" ColumnSpacing="0" Grid.Row="0" Grid.Column="1" VerticalOptions="Center" Padding="0, 7"> <Grid RowSpacing="0" ColumnSpacing="0" Grid.Row="0" Grid.Column="1" VerticalOptions="Center" Padding="0, 7">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
@@ -121,4 +119,4 @@
SemanticProperties.Description="{u:I18n Options}" SemanticProperties.Description="{u:I18n Options}"
AutomationId="CipherOptionsButton" /> AutomationId="CipherOptionsButton" />
</controls:ExtendedGrid> </controls:BaseCipherViewCell>

View File

@@ -5,7 +5,7 @@ using Bit.Core.Utilities;
namespace Bit.App.Controls namespace Bit.App.Controls
{ {
public partial class CipherViewCell : ExtendedGrid public partial class CipherViewCell : BaseCipherViewCell
{ {
private const int ICON_COLUMN_DEFAULT_WIDTH = 40; private const int ICON_COLUMN_DEFAULT_WIDTH = 40;
private const int ICON_IMAGE_DEFAULT_WIDTH = 22; private const int ICON_IMAGE_DEFAULT_WIDTH = 22;
@@ -23,6 +23,10 @@ namespace Bit.App.Controls
_iconImage.HeightRequest = ICON_IMAGE_DEFAULT_WIDTH * fontScale; _iconImage.HeightRequest = ICON_IMAGE_DEFAULT_WIDTH * fontScale;
} }
protected override CachedImage Icon => _iconImage;
protected override IconLabel IconPlaceholder => _iconPlaceholderImage;
public ICommand ButtonCommand public ICommand ButtonCommand
{ {
get => GetValue(ButtonCommandProperty) as ICommand; get => GetValue(ButtonCommandProperty) as ICommand;

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<ContentView <ContentView
xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
@@ -17,7 +17,7 @@
LineBreakMode="TailTruncation" /> LineBreakMode="TailTruncation" />
<controls:IconLabel <controls:IconLabel
Text="{Binding Source={x:Static core:BitwardenIcons.ShareSquare}}" Text="{Binding Source={x:Static core:BitwardenIcons.ExternalLink}}"
TextColor="{DynamicResource TextColor}" TextColor="{DynamicResource TextColor}"
HorizontalOptions="End" HorizontalOptions="End"
VerticalOptions="Center" VerticalOptions="Center"

View File

@@ -79,6 +79,7 @@
<Folder Include="Resources\Localization\" /> <Folder Include="Resources\Localization\" />
<Folder Include="Utilities\Fido2\" /> <Folder Include="Utilities\Fido2\" />
<Folder Include="Controls\Picker\" /> <Folder Include="Controls\Picker\" />
<Folder Include="Controls\Avatar\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<MauiImage Include="Resources\Images\dotnet_bot.svg"> <MauiImage Include="Resources\Images\dotnet_bot.svg">
@@ -109,5 +110,6 @@
<ItemGroup> <ItemGroup>
<None Remove="Utilities\Fido2\" /> <None Remove="Utilities\Fido2\" />
<None Remove="Controls\Picker\" /> <None Remove="Controls\Picker\" />
<None Remove="Controls\Avatar\" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -6,7 +6,7 @@
public const string HELP_ABOUT_ORGANIZATIONS = "https://bitwarden.com/help/about-organizations/"; public const string HELP_ABOUT_ORGANIZATIONS = "https://bitwarden.com/help/about-organizations/";
public const string HELP_FINGERPRINT_PHRASE = "https://bitwarden.com/help/fingerprint-phrase/"; public const string HELP_FINGERPRINT_PHRASE = "https://bitwarden.com/help/fingerprint-phrase/";
public const string CONTACT_SUPPORT = "https://bitwarden.com/contact/"; public const string PRIVACY_POLICY = "https://bitwarden.com/privacy/";
/// <summary> /// <summary>
/// Link to go to settings website. Requires to pass website URL as parameter. /// Link to go to settings website. Requires to pass website URL as parameter.

View File

@@ -1,4 +1,5 @@
using Camera.MAUI; using Bit.App.Controls;
using Camera.MAUI;
using CommunityToolkit.Maui; using CommunityToolkit.Maui;
#if !UT #if !UT
using FFImageLoading.Maui; using FFImageLoading.Maui;
@@ -62,6 +63,13 @@ public static class MauiProgram
builder.Logging.AddDebug(); builder.Logging.AddDebug();
#endif #endif
ExplicitlyPreventThingsGetRemovedBecauseOfLinker();
return builder; return builder;
} }
private static void ExplicitlyPreventThingsGetRemovedBecauseOfLinker()
{
StubBaseCipherViewCellSoLinkerDoesntRemoveMethods.CallThisSoLinkerDoesntRemoveMethods();
}
} }

View File

@@ -6,5 +6,6 @@ namespace Bit.Core.Models.Api
{ {
public string Uri { get; set; } public string Uri { get; set; }
public UriMatchType? Match { get; set; } public UriMatchType? Match { get; set; }
public string UriChecksum { get; set; }
} }
} }

View File

@@ -11,9 +11,11 @@ namespace Bit.Core.Models.Data
{ {
Uri = data.Uri; Uri = data.Uri;
Match = data.Match; Match = data.Match;
UriChecksum = data.UriChecksum;
} }
public string Uri { get; set; } public string Uri { get; set; }
public UriMatchType? Match { get; set; } public UriMatchType? Match { get; set; }
public string UriChecksum { get; set; }
} }
} }

View File

@@ -115,7 +115,7 @@ namespace Bit.Core.Models.Domain
switch (Type) switch (Type)
{ {
case Enums.CipherType.Login: case Enums.CipherType.Login:
model.Login = await Login.DecryptAsync(OrganizationId, model.Key); model.Login = await Login.DecryptAsync(OrganizationId, Key == null, model.Key);
break; break;
case Enums.CipherType.SecureNote: case Enums.CipherType.SecureNote:
model.SecureNote = await SecureNote.DecryptAsync(OrganizationId, model.Key); model.SecureNote = await SecureNote.DecryptAsync(OrganizationId, model.Key);

View File

@@ -2,8 +2,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.Core.Abstractions;
using Bit.Core.Models.Data; using Bit.Core.Models.Data;
using Bit.Core.Models.View; using Bit.Core.Models.View;
using Bit.Core.Utilities;
namespace Bit.Core.Models.Domain namespace Bit.Core.Models.Domain
{ {
@@ -31,7 +33,7 @@ namespace Bit.Core.Models.Domain
public EncString Totp { get; set; } public EncString Totp { get; set; }
public List<Fido2Credential> Fido2Credentials { get; set; } public List<Fido2Credential> Fido2Credentials { get; set; }
public async Task<LoginView> DecryptAsync(string orgId, SymmetricCryptoKey key = null) public async Task<LoginView> DecryptAsync(string orgId, bool bypassUriChecksumValidation, SymmetricCryptoKey key = null)
{ {
var view = await DecryptObjAsync(new LoginView(this), this, new HashSet<string> var view = await DecryptObjAsync(new LoginView(this), this, new HashSet<string>
{ {
@@ -41,10 +43,15 @@ namespace Bit.Core.Models.Domain
}, orgId, key); }, orgId, key);
if (Uris != null) if (Uris != null)
{ {
var cryptoService = ServiceContainer.Resolve<ICryptoService>();
view.Uris = new List<LoginUriView>(); view.Uris = new List<LoginUriView>();
foreach (var uri in Uris) foreach (var uri in Uris)
{ {
view.Uris.Add(await uri.DecryptAsync(orgId, key)); var loginUriView = await uri.DecryptAsync(orgId, key);
if (bypassUriChecksumValidation || await cryptoService.ValidateUriChecksumAsync(uri.UriChecksum, loginUriView.Uri, orgId, key))
{
view.Uris.Add(loginUriView);
}
} }
} }
if (Fido2Credentials != null) if (Fido2Credentials != null)

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Models.Data; using Bit.Core.Models.Data;
@@ -10,7 +11,8 @@ namespace Bit.Core.Models.Domain
{ {
private HashSet<string> _map = new HashSet<string> private HashSet<string> _map = new HashSet<string>
{ {
"Uri" nameof(Uri),
nameof(UriChecksum)
}; };
public LoginUri() { } public LoginUri() { }
@@ -23,10 +25,11 @@ namespace Bit.Core.Models.Domain
public EncString Uri { get; set; } public EncString Uri { get; set; }
public UriMatchType? Match { get; set; } public UriMatchType? Match { get; set; }
public EncString UriChecksum { get; set; }
public Task<LoginUriView> DecryptAsync(string orgId, SymmetricCryptoKey key = null) public Task<LoginUriView> DecryptAsync(string orgId, SymmetricCryptoKey key = null)
{ {
return DecryptObjAsync(new LoginUriView(this), this, _map, orgId, key); return DecryptObjAsync(new LoginUriView(this), this, _map.Where(m => m != nameof(UriChecksum)).ToHashSet<string>(), orgId, key);
} }
public LoginUriData ToLoginUriData() public LoginUriData ToLoginUriData()

View File

@@ -17,10 +17,12 @@ namespace Bit.Core.Models.Export
{ {
Match = obj.Match; Match = obj.Match;
Uri = obj.Uri?.EncryptedString; Uri = obj.Uri?.EncryptedString;
UriChecksum = obj.UriChecksum?.EncryptedString;
} }
public UriMatchType? Match { get; set; } public UriMatchType? Match { get; set; }
public string Uri { get; set; } public string Uri { get; set; }
public string UriChecksum { get; set; }
public static LoginUriView ToView(LoginUri req, LoginUriView view = null) public static LoginUriView ToView(LoginUri req, LoginUriView view = null)
{ {

View File

@@ -27,7 +27,7 @@ namespace Bit.Core.Models.Request
Login = new LoginApi Login = new LoginApi
{ {
Uris = cipher.Login.Uris?.Select( Uris = cipher.Login.Uris?.Select(
u => new LoginUriApi { Match = u.Match, Uri = u.Uri?.EncryptedString }).ToList(), u => new LoginUriApi { Match = u.Match, Uri = u.Uri?.EncryptedString, UriChecksum = u.UriChecksum?.EncryptedString }).ToList(),
Username = cipher.Login.Username?.EncryptedString, Username = cipher.Login.Username?.EncryptedString,
Password = cipher.Login.Password?.EncryptedString, Password = cipher.Login.Password?.EncryptedString,
PasswordRevisionDate = cipher.Login.PasswordRevisionDate, PasswordRevisionDate = cipher.Login.PasswordRevisionDate,

View File

@@ -37,7 +37,7 @@
Text="{Binding BaseUrl}" Text="{Binding BaseUrl}"
Keyboard="Url" Keyboard="Url"
Placeholder="ex. https://bitwarden.company.com" Placeholder="ex. https://bitwarden.company.com"
StyleClass="box-value" StyleClass="box-value, no-keyboard-auto-help"
ReturnType="Go" ReturnType="Go"
ReturnCommand="{Binding SubmitCommand}" ReturnCommand="{Binding SubmitCommand}"
AutomationId="ServerUrlEntry"/> AutomationId="ServerUrlEntry"/>
@@ -59,7 +59,7 @@
x:Name="_webVaultEntry" x:Name="_webVaultEntry"
Text="{Binding WebVaultUrl}" Text="{Binding WebVaultUrl}"
Keyboard="Url" Keyboard="Url"
StyleClass="box-value" StyleClass="box-value, no-keyboard-auto-help"
AutomationId="WebVaultUrlEntry"/> AutomationId="WebVaultUrlEntry"/>
</StackLayout> </StackLayout>
<StackLayout StyleClass="box-row"> <StackLayout StyleClass="box-row">
@@ -70,7 +70,7 @@
x:Name="_apiEntry" x:Name="_apiEntry"
Text="{Binding ApiUrl}" Text="{Binding ApiUrl}"
Keyboard="Url" Keyboard="Url"
StyleClass="box-value" StyleClass="box-value, no-keyboard-auto-help"
AutomationId="ApiUrlEntry"/> AutomationId="ApiUrlEntry"/>
</StackLayout> </StackLayout>
<StackLayout StyleClass="box-row"> <StackLayout StyleClass="box-row">
@@ -81,7 +81,7 @@
x:Name="_identityEntry" x:Name="_identityEntry"
Text="{Binding IdentityUrl}" Text="{Binding IdentityUrl}"
Keyboard="Url" Keyboard="Url"
StyleClass="box-value" StyleClass="box-value, no-keyboard-auto-help"
AutomationId="IdentityUrlEntry"/> AutomationId="IdentityUrlEntry"/>
</StackLayout> </StackLayout>
<StackLayout StyleClass="box-row"> <StackLayout StyleClass="box-row">
@@ -92,7 +92,7 @@
x:Name="_iconsEntry" x:Name="_iconsEntry"
Text="{Binding IconsUrl}" Text="{Binding IconsUrl}"
Keyboard="Url" Keyboard="Url"
StyleClass="box-value" StyleClass="box-value, no-keyboard-auto-help"
ReturnType="Go" ReturnType="Go"
ReturnCommand="{Binding SubmitCommand}" ReturnCommand="{Binding SubmitCommand}"
AutomationId="IconsUrlEntry"/> AutomationId="IconsUrlEntry"/>

View File

@@ -50,11 +50,10 @@
x:Name="_email" x:Name="_email"
Text="{Binding Email}" Text="{Binding Email}"
Keyboard="Email" Keyboard="Email"
StyleClass="box-value" StyleClass="box-value, no-keyboard-auto-help"
ReturnType="Go" ReturnType="Go"
ReturnCommand="{Binding ContinueCommand}" ReturnCommand="{Binding ContinueCommand}"
AutomationId="EmailAddressEntry" AutomationId="EmailAddressEntry">
>
<VisualStateManager.VisualStateGroups> <VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">

View File

@@ -153,7 +153,7 @@ namespace Bit.App.Pages
private async Task StartEnvironmentAsync() private async Task StartEnvironmentAsync()
{ {
await _accountListOverlay.HideAsync(); await _accountListOverlay.HideAsync();
var page = new EnvironmentPage(); var page = new EnvironmentPage();
await Navigation.PushModalAsync(new NavigationPage(page)); await Navigation.PushModalAsync(new NavigationPage(page));
} }

View File

@@ -81,7 +81,7 @@ namespace Bit.App.Pages
{ {
if (message.Command == Constants.ClearSensitiveFields) if (message.Command == Constants.ClearSensitiveFields)
{ {
MainThread.BeginInvokeOnMainThread(_vm.ResetPinPasswordFields); MainThread.BeginInvokeOnMainThread(() => _vm?.ResetPinPasswordFields());
} }
}); });
if (_appeared) if (_appeared)

View File

@@ -245,9 +245,9 @@ namespace Bit.App.Pages
public async Task SubmitAsync() public async Task SubmitAsync()
{ {
ShowPassword = false;
try try
{ {
ShowPassword = false;
var kdfConfig = await _stateService.GetActiveUserCustomDataAsync(a => new KdfConfig(a?.Profile)); var kdfConfig = await _stateService.GetActiveUserCustomDataAsync(a => new KdfConfig(a?.Profile));
if (PinEnabled) if (PinEnabled)
{ {
@@ -257,12 +257,15 @@ namespace Bit.App.Pages
{ {
await UnlockWithMasterPasswordAsync(kdfConfig); await UnlockWithMasterPasswordAsync(kdfConfig);
} }
} }
catch (LegacyUserException) catch (LegacyUserException)
{ {
await HandleLegacyUserAsync(); await HandleLegacyUserAsync();
} }
catch (Exception ex)
{
HandleException(ex);
}
} }
private async Task UnlockWithPinAsync(KdfConfig kdfConfig) private async Task UnlockWithPinAsync(KdfConfig kdfConfig)

View File

@@ -3,6 +3,7 @@ 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.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
namespace Bit.App.Pages namespace Bit.App.Pages
@@ -74,7 +75,7 @@ namespace Bit.App.Pages
{ {
if (message.Command == Constants.ClearSensitiveFields) if (message.Command == Constants.ClearSensitiveFields)
{ {
MainThread.BeginInvokeOnMainThread(_vm.ResetPasswordField); MainThread.BeginInvokeOnMainThread(() => _vm?.ResetPasswordField());
} }
}); });
_mainContent.Content = _mainLayout; _mainContent.Content = _mainLayout;
@@ -188,12 +189,20 @@ namespace Bit.App.Pages
private async Task LogInSuccessAsync() private async Task LogInSuccessAsync()
{ {
if (AppHelpers.SetAlternateMainPage(_appOptions)) try
{ {
return; if (AppHelpers.SetAlternateMainPage(_appOptions))
{
return;
}
var previousPage = await AppHelpers.ClearPreviousPage();
App.MainPage = new TabsPage(_appOptions, previousPage);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
throw;
} }
var previousPage = await AppHelpers.ClearPreviousPage();
App.MainPage = new TabsPage(_appOptions, previousPage);
} }
private async Task UpdateTempPasswordAsync() private async Task UpdateTempPasswordAsync()

View File

@@ -1,6 +1,7 @@
using Bit.App.Models; using Bit.App.Models;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Services;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@@ -48,12 +49,20 @@ namespace Bit.App.Pages
private async Task LogInSuccessAsync() private async Task LogInSuccessAsync()
{ {
if (AppHelpers.SetAlternateMainPage(_appOptions)) try
{ {
return; if (AppHelpers.SetAlternateMainPage(_appOptions))
{
return;
}
var previousPage = await AppHelpers.ClearPreviousPage();
App.MainPage = new TabsPage(_appOptions, previousPage);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
throw;
} }
var previousPage = await AppHelpers.ClearPreviousPage();
App.MainPage = new TabsPage(_appOptions, previousPage);
} }
private async Task UpdateTempPasswordAsync() private async Task UpdateTempPasswordAsync()

View File

@@ -77,6 +77,7 @@ namespace Bit.App.Pages
{ {
_requestTimeCts?.Cancel(); _requestTimeCts?.Cancel();
_requestTimeCts?.Dispose(); _requestTimeCts?.Dispose();
_requestTimeCts = null;
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -1,6 +1,7 @@
using Bit.App.Models; using Bit.App.Models;
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 Bit.Core.Utilities;
namespace Bit.App.Pages namespace Bit.App.Pages
@@ -89,16 +90,30 @@ namespace Bit.App.Pages
private async Task StartTwoFactorAsync() private async Task StartTwoFactorAsync()
{ {
RestoreAppOptionsFromCopy(); try
var page = new TwoFactorPage(true, _appOptions, _vm.OrgIdentifier); {
await Navigation.PushModalAsync(new NavigationPage(page)); RestoreAppOptionsFromCopy();
var page = new TwoFactorPage(true, _appOptions, _vm.OrgIdentifier);
await Navigation.PushModalAsync(new NavigationPage(page));
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
private async Task StartSetPasswordAsync() private async Task StartSetPasswordAsync()
{ {
RestoreAppOptionsFromCopy(); try
var page = new SetPasswordPage(_appOptions, _vm.OrgIdentifier); {
await Navigation.PushModalAsync(new NavigationPage(page)); RestoreAppOptionsFromCopy();
var page = new SetPasswordPage(_appOptions, _vm.OrgIdentifier);
await Navigation.PushModalAsync(new NavigationPage(page));
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
private async Task UpdateTempPasswordAsync() private async Task UpdateTempPasswordAsync()
@@ -115,16 +130,23 @@ namespace Bit.App.Pages
private async Task SsoAuthSuccessAsync() private async Task SsoAuthSuccessAsync()
{ {
RestoreAppOptionsFromCopy(); try
await AppHelpers.ClearPreviousPage(); {
RestoreAppOptionsFromCopy();
await AppHelpers.ClearPreviousPage();
if (await _vaultTimeoutService.IsLockedAsync()) if (await _vaultTimeoutService.IsLockedAsync())
{ {
App.MainPage = new NavigationPage(new LockPage(_appOptions)); App.MainPage = new NavigationPage(new LockPage(_appOptions));
}
else
{
App.MainPage = new TabsPage(_appOptions, null);
}
} }
else catch (Exception ex)
{ {
App.MainPage = new TabsPage(_appOptions, null); LoggerHelper.LogEvenIfCantBeResolved(ex);
} }
} }
} }

View File

@@ -1,5 +1,6 @@
using Bit.App.Models; using Bit.App.Models;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.Core.Services;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@@ -64,12 +65,19 @@ namespace Bit.App.Pages
private async Task SetPasswordSuccessAsync() private async Task SetPasswordSuccessAsync()
{ {
if (AppHelpers.SetAlternateMainPage(_appOptions)) try
{ {
return; if (AppHelpers.SetAlternateMainPage(_appOptions))
{
return;
}
var previousPage = await AppHelpers.ClearPreviousPage();
App.MainPage = new TabsPage(_appOptions, previousPage);
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
} }
var previousPage = await AppHelpers.ClearPreviousPage();
App.MainPage = new TabsPage(_appOptions, previousPage);
} }
} }
} }

View File

@@ -133,12 +133,12 @@
</StackLayout> </StackLayout>
</StackLayout> </StackLayout>
<StackLayout Spacing="0" Padding="0" IsVisible="{Binding DuoMethod, Mode=OneWay}" <StackLayout Spacing="0" Padding="0" IsVisible="{Binding DuoMethod, Mode=OneWay}"
VerticalOptions="FillAndExpand"> VerticalOptions="StartAndExpand">
<controls:HybridWebView <controls:HybridWebView
x:Name="_duoWebView" x:Name="_duoWebView"
HorizontalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
MinimumHeightRequest="400" /> HeightRequest="{Binding DuoWebViewHeight, Mode=OneWay}" />
<StackLayout StyleClass="box" VerticalOptions="End"> <StackLayout StyleClass="box" VerticalOptions="End">
<StackLayout StyleClass="box-row, box-row-switch"> <StackLayout StyleClass="box-row, box-row-switch">
<Label <Label

View File

@@ -2,6 +2,7 @@
using Bit.App.Models; using Bit.App.Models;
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 Bit.Core.Utilities;
namespace Bit.App.Pages namespace Bit.App.Pages
@@ -63,11 +64,11 @@ namespace Bit.App.Pages
if (_vm.YubikeyMethod && !string.IsNullOrWhiteSpace(token) && if (_vm.YubikeyMethod && !string.IsNullOrWhiteSpace(token) &&
token.Length == 44 && !token.Contains(" ")) token.Length == 44 && !token.Contains(" "))
{ {
MainThread.BeginInvokeOnMainThread(async () => MainThread.BeginInvokeOnMainThread(() =>
{ {
_vm.Token = token; _vm.Token = token;
await _vm.SubmitAsync();
}); });
_vm.SubmitCommand.Execute(null);
} }
} }
else if (message.Command == "resumeYubiKey") else if (message.Command == "resumeYubiKey")
@@ -124,12 +125,9 @@ namespace Bit.App.Pages
return base.OnBackButtonPressed(); return base.OnBackButtonPressed();
} }
private async void Continue_Clicked(object sender, EventArgs e) private void Continue_Clicked(object sender, EventArgs e)
{ {
if (DoOnce()) _vm.SubmitCommand.Execute(null);
{
await _vm.SubmitAsync();
}
} }
private async void Methods_Clicked(object sender, EventArgs e) private async void Methods_Clicked(object sender, EventArgs e)
@@ -158,17 +156,24 @@ namespace Bit.App.Pages
private async void TryAgain_Clicked(object sender, EventArgs e) private async void TryAgain_Clicked(object sender, EventArgs e)
{ {
if (DoOnce()) try
{ {
if (_vm.Fido2Method) if (DoOnce())
{ {
await _vm.Fido2AuthenticateAsync(); if (_vm.Fido2Method)
} {
else if (_vm.YubikeyMethod) await _vm.Fido2AuthenticateAsync();
{ }
_messagingService.Send("listenYubiKeyOTP", true); else if (_vm.YubikeyMethod)
{
_messagingService.Send("listenYubiKeyOTP", true);
}
} }
} }
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
} }
private async Task StartSetPasswordAsync() private async Task StartSetPasswordAsync()

View File

@@ -1,25 +1,16 @@
using System; using System.Net;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.Core.Resources.Localization;
using Bit.App.Utilities; using Bit.App.Utilities;
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.Domain; using Bit.Core.Models.Domain;
using Bit.Core.Models.Request; using Bit.Core.Models.Request;
using Bit.Core.Services; using Bit.Core.Resources.Localization;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Newtonsoft.Json; using Newtonsoft.Json;
using Microsoft.Maui.Authentication;
using Microsoft.Maui.Controls;
using Microsoft.Maui;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
public class TwoFactorPageViewModel : CaptchaProtectedViewModel public class TwoFactorPageViewModel : CaptchaProtectedViewModel
@@ -43,6 +34,7 @@ namespace Bit.App.Pages
private string _webVaultUrl = "https://vault.bitwarden.com"; private string _webVaultUrl = "https://vault.bitwarden.com";
private bool _enableContinue = false; private bool _enableContinue = false;
private bool _showContinue = true; private bool _showContinue = true;
private double _duoWebViewHeight;
public TwoFactorPageViewModel() public TwoFactorPageViewModel()
{ {
@@ -62,7 +54,7 @@ namespace Bit.App.Pages
_deviceTrustCryptoService = ServiceContainer.Resolve<IDeviceTrustCryptoService>(); _deviceTrustCryptoService = ServiceContainer.Resolve<IDeviceTrustCryptoService>();
PageTitle = AppResources.TwoStepLogin; PageTitle = AppResources.TwoStepLogin;
SubmitCommand = new Command(async () => await SubmitAsync()); SubmitCommand = CreateDefaultAsyncRelayCommand(() => MainThread.InvokeOnMainThreadAsync(async () => await SubmitAsync()), allowsMultipleExecutions: false);
MoreCommand = CreateDefaultAsyncRelayCommand(MoreAsync, onException: _logger.Exception, allowsMultipleExecutions: false); MoreCommand = CreateDefaultAsyncRelayCommand(MoreAsync, onException: _logger.Exception, allowsMultipleExecutions: false);
} }
@@ -72,6 +64,12 @@ namespace Bit.App.Pages
set => SetProperty(ref _totpInstruction, value); set => SetProperty(ref _totpInstruction, value);
} }
public double DuoWebViewHeight
{
get => _duoWebViewHeight;
set => SetProperty(ref _duoWebViewHeight, value);
}
public bool Remember { get; set; } public bool Remember { get; set; }
public bool AuthingWithSso { get; set; } public bool AuthingWithSso { get; set; }
@@ -91,8 +89,7 @@ namespace Bit.App.Pages
public bool TotpMethod => AuthenticatorMethod || EmailMethod; public bool TotpMethod => AuthenticatorMethod || EmailMethod;
public bool ShowTryAgain => (YubikeyMethod && // TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes public bool ShowTryAgain => (YubikeyMethod && DeviceInfo.Platform == DevicePlatform.iOS) || Fido2Method;
Device.RuntimePlatform == Device.iOS) || Fido2Method;
public bool ShowContinue public bool ShowContinue
{ {
@@ -106,9 +103,11 @@ Device.RuntimePlatform == Device.iOS) || Fido2Method;
set => SetProperty(ref _enableContinue, value); set => SetProperty(ref _enableContinue, value);
} }
public string YubikeyInstruction => // TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes #if IOS
Device.RuntimePlatform == Device.iOS ? AppResources.YubiKeyInstructionIos : public string YubikeyInstruction => AppResources.YubiKeyInstructionIos;
AppResources.YubiKeyInstruction; #else
public string YubikeyInstruction => AppResources.YubiKeyInstruction;
#endif
public TwoFactorProviderType? SelectedProviderType public TwoFactorProviderType? SelectedProviderType
{ {
@@ -124,7 +123,7 @@ Device.RuntimePlatform == Device.iOS ? AppResources.YubiKeyInstructionIos :
nameof(ShowTryAgain), nameof(ShowTryAgain),
}); });
} }
public Command SubmitCommand { get; } public ICommand SubmitCommand { get; }
public ICommand MoreCommand { get; } public ICommand MoreCommand { get; }
public Action TwoFactorAuthSuccessAction { get; set; } public Action TwoFactorAuthSuccessAction { get; set; }
public Action LockAction { get; set; } public Action LockAction { get; set; }
@@ -180,13 +179,14 @@ Device.RuntimePlatform == Device.iOS ? AppResources.YubiKeyInstructionIos :
break; break;
case TwoFactorProviderType.Duo: case TwoFactorProviderType.Duo:
case TwoFactorProviderType.OrganizationDuo: case TwoFactorProviderType.OrganizationDuo:
SetDuoWebViewHeight();
var host = WebUtility.UrlEncode(providerData["Host"] as string); var host = WebUtility.UrlEncode(providerData["Host"] as string);
var req = WebUtility.UrlEncode(providerData["Signature"] as string); var req = WebUtility.UrlEncode(providerData["Signature"] as string);
page.DuoWebView.Uri = $"{_webVaultUrl}/duo-connector.html?host={host}&request={req}"; page.DuoWebView.Uri = $"{_webVaultUrl}/duo-connector.html?host={host}&request={req}";
page.DuoWebView.RegisterAction(sig => page.DuoWebView.RegisterAction(sig =>
{ {
Token = sig; Token = sig;
Device.BeginInvokeOnMainThread(async () => await SubmitAsync()); SubmitCommand.Execute(null);
}); });
break; break;
case TwoFactorProviderType.Email: case TwoFactorProviderType.Email:
@@ -211,70 +211,84 @@ Device.RuntimePlatform == Device.iOS ? AppResources.YubiKeyInstructionIos :
ShowContinue = !(SelectedProviderType == null || DuoMethod || Fido2Method); ShowContinue = !(SelectedProviderType == null || DuoMethod || Fido2Method);
} }
public void SetDuoWebViewHeight()
{
var screenHeight = DeviceDisplay.MainDisplayInfo.Height / DeviceDisplay.MainDisplayInfo.Density;
DuoWebViewHeight = screenHeight > 0 ? (screenHeight / 8) * 6 : 400;
}
public async Task Fido2AuthenticateAsync(Dictionary<string, object> providerData = null) public async Task Fido2AuthenticateAsync(Dictionary<string, object> providerData = null)
{ {
await _deviceActionService.ShowLoadingAsync(AppResources.Validating);
if (providerData == null)
{
providerData = _authService.TwoFactorProvidersData[TwoFactorProviderType.Fido2WebAuthn];
}
var callbackUri = "bitwarden://webauthn-callback";
var data = AppHelpers.EncodeDataParameter(new
{
callbackUri = callbackUri,
data = JsonConvert.SerializeObject(providerData),
headerText = AppResources.Fido2Title,
btnText = AppResources.Fido2AuthenticateWebAuthn,
btnReturnText = AppResources.Fido2ReturnToApp,
});
var url = _webVaultUrl + "/webauthn-mobile-connector.html?" + "data=" + data +
"&parent=" + Uri.EscapeDataString(callbackUri) + "&v=2";
WebAuthenticatorResult authResult = null;
try try
{ {
var options = new WebAuthenticatorOptions await _deviceActionService.ShowLoadingAsync(AppResources.Validating);
{
Url = new Uri(url),
CallbackUrl = new Uri(callbackUri),
PrefersEphemeralWebBrowserSession = true,
};
authResult = await WebAuthenticator.AuthenticateAsync(options);
}
catch (TaskCanceledException)
{
// user canceled
await _deviceActionService.HideLoadingAsync();
return;
}
string response = null; if (providerData == null)
if (authResult != null && authResult.Properties.TryGetValue("data", out var resultData))
{
response = Uri.UnescapeDataString(resultData);
}
if (!string.IsNullOrWhiteSpace(response))
{
Token = response;
await SubmitAsync(false);
}
else
{
await _deviceActionService.HideLoadingAsync();
if (authResult != null && authResult.Properties.TryGetValue("error", out var resultError))
{ {
var message = AppResources.Fido2CheckBrowser + "\n\n" + resultError; providerData = _authService.TwoFactorProvidersData[TwoFactorProviderType.Fido2WebAuthn];
await _platformUtilsService.ShowDialogAsync(message, AppResources.AnErrorHasOccurred, }
AppResources.Ok);
var callbackUri = "bitwarden://webauthn-callback";
var data = AppHelpers.EncodeDataParameter(new
{
callbackUri = callbackUri,
data = JsonConvert.SerializeObject(providerData),
headerText = AppResources.Fido2Title,
btnText = AppResources.Fido2AuthenticateWebAuthn,
btnReturnText = AppResources.Fido2ReturnToApp,
});
var url = _webVaultUrl + "/webauthn-mobile-connector.html?" + "data=" + data +
"&parent=" + Uri.EscapeDataString(callbackUri) + "&v=2";
WebAuthenticatorResult authResult = null;
try
{
var options = new WebAuthenticatorOptions
{
Url = new Uri(url),
CallbackUrl = new Uri(callbackUri),
PrefersEphemeralWebBrowserSession = true,
};
authResult = await WebAuthenticator.AuthenticateAsync(options);
}
catch (TaskCanceledException)
{
// user canceled
await _deviceActionService.HideLoadingAsync();
return;
}
string response = null;
if (authResult != null && authResult.Properties.TryGetValue("data", out var resultData))
{
response = Uri.UnescapeDataString(resultData);
}
if (!string.IsNullOrWhiteSpace(response))
{
Token = response;
await SubmitAsync(false);
} }
else else
{ {
await _platformUtilsService.ShowDialogAsync(AppResources.Fido2CheckBrowser, await _deviceActionService.HideLoadingAsync();
AppResources.AnErrorHasOccurred, AppResources.Ok); if (authResult != null && authResult.Properties.TryGetValue("error", out var resultError))
{
var message = AppResources.Fido2CheckBrowser + "\n\n" + resultError;
await _platformUtilsService.ShowDialogAsync(message, AppResources.AnErrorHasOccurred,
AppResources.Ok);
}
else
{
await _platformUtilsService.ShowDialogAsync(AppResources.Fido2CheckBrowser,
AppResources.AnErrorHasOccurred, AppResources.Ok);
}
} }
}
catch (Exception ex)
{
HandleException(ex);
} }
} }

View File

@@ -170,8 +170,15 @@ namespace Bit.App.Pages
{ {
Task.Run(async () => Task.Run(async () =>
{ {
await Task.Delay(ShowModalAnimationDelay); try
MainThread.BeginInvokeOnMainThread(() => input.Focus()); {
await Task.Delay(ShowModalAnimationDelay);
MainThread.BeginInvokeOnMainThread(() => input.Focus());
}
catch (Exception ex)
{
_logger.Value.Exception(ex);
}
}); });
} }

View File

@@ -31,8 +31,8 @@
<BoxView StyleClass="box-row-separator" /> <BoxView StyleClass="box-row-separator" />
<controls:ExternalLinkItemView <controls:ExternalLinkItemView
Title="{u:I18n ContactBitwardenSupport}" Title="{u:I18n PrivacyPolicy}"
GoToLinkCommand="{Binding ContactBitwardenSupportCommand}" GoToLinkCommand="{Binding GoToPrivacyPolicyCommand}"
StyleClass="settings-external-link-item" StyleClass="settings-external-link-item"
HorizontalOptions="FillAndExpand" /> HorizontalOptions="FillAndExpand" />
<BoxView StyleClass="box-row-separator" /> <BoxView StyleClass="box-row-separator" />

View File

@@ -33,10 +33,10 @@ namespace Bit.App.Pages
AppResources.ContinueToHelpCenter, AppResources.ContinueToHelpCenter,
ExternalLinksConstants.HELP_CENTER), allowsMultipleExecutions: false); ExternalLinksConstants.HELP_CENTER), allowsMultipleExecutions: false);
ContactBitwardenSupportCommand = CreateDefaultAsyncRelayCommand( GoToPrivacyPolicyCommand = CreateDefaultAsyncRelayCommand(
() => LaunchUriAsync(AppResources.ContactSupportDescriptionLong, () => LaunchUriAsync(AppResources.PrivacyPolicyDescriptionLong,
AppResources.ContinueToContactSupport, AppResources.ContinueToPrivacyPolicy,
ExternalLinksConstants.CONTACT_SUPPORT), allowsMultipleExecutions: false); ExternalLinksConstants.PRIVACY_POLICY), allowsMultipleExecutions: false);
GoToWebVaultCommand = CreateDefaultAsyncRelayCommand( GoToWebVaultCommand = CreateDefaultAsyncRelayCommand(
() => LaunchUriAsync(AppResources.ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp, () => LaunchUriAsync(AppResources.ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp,
@@ -80,7 +80,7 @@ namespace Bit.App.Pages
public AsyncRelayCommand ToggleSubmitCrashLogsCommand { get; } public AsyncRelayCommand ToggleSubmitCrashLogsCommand { get; }
public ICommand GoToHelpCenterCommand { get; } public ICommand GoToHelpCenterCommand { get; }
public ICommand ContactBitwardenSupportCommand { get; } public ICommand GoToPrivacyPolicyCommand { get; }
public ICommand GoToWebVaultCommand { get; } public ICommand GoToWebVaultCommand { get; }
public ICommand GoToLearnAboutOrgsCommand { get; } public ICommand GoToLearnAboutOrgsCommand { get; }
public ICommand RateTheAppCommand { get; } public ICommand RateTheAppCommand { get; }

View File

@@ -93,6 +93,7 @@
<controls:CustomLabel <controls:CustomLabel
StyleClass="box-label-regular" StyleClass="box-label-regular"
Text="{u:I18n NoPendingRequests}" Text="{u:I18n NoPendingRequests}"
IsVisible="{Binding HasLoginRequests, Converter={StaticResource inverseBool}}"
FontAttributes="{OnPlatform iOS=Bold}" FontAttributes="{OnPlatform iOS=Bold}"
FontWeight="500" FontWeight="500"
HorizontalTextAlignment="Center" HorizontalTextAlignment="Center"

View File

@@ -38,5 +38,11 @@ namespace Bit.App.Pages
return _iconImageSource; return _iconImageSource;
} }
} }
/// <summary>
/// Flag that indicates if FFImageLoading has successfully finished loading the image.
/// This is useful to check when the cell is being reused.
/// </summary>
public bool IconImageSuccesfullyLoaded { get; set; }
} }
} }

View File

@@ -47,6 +47,9 @@
Camera="{Binding Camera}" Camera="{Binding Camera}"
AutoStartPreview="{Binding AutoStartPreview}" AutoStartPreview="{Binding AutoStartPreview}"
NumCamerasDetected="{Binding NumCameras, Mode=OneWayToSource}" NumCamerasDetected="{Binding NumCameras, Mode=OneWayToSource}"
WidthRequest="{OnPlatform Android=150}"
HeightRequest="{OnPlatform Android=150}"
Scale="{OnPlatform Android=4}"
Grid.Column="0" Grid.Column="0"
Grid.Row="0" Grid.Row="0"
Grid.RowSpan="3" /> Grid.RowSpan="3" />

View File

@@ -1723,6 +1723,15 @@ namespace Bit.Core.Resources.Localization {
} }
} }
/// <summary>
/// Looks up a localized string similar to Continue to privacy policy?.
/// </summary>
public static string ContinueToPrivacyPolicy {
get {
return ResourceManager.GetString("ContinueToPrivacyPolicy", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Continue to web app?. /// Looks up a localized string similar to Continue to web app?.
/// </summary> /// </summary>
@@ -5525,6 +5534,15 @@ namespace Bit.Core.Resources.Localization {
} }
} }
/// <summary>
/// Looks up a localized string similar to Check out our privacy policy on bitwarden.com..
/// </summary>
public static string PrivacyPolicyDescriptionLong {
get {
return ResourceManager.GetString("PrivacyPolicyDescriptionLong", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Bitwarden keeps your vault automatically synced by using push notifications. For the best possible experience, please select &quot;Allow&quot; on the following prompt when asked to allow push notifications.. /// Looks up a localized string similar to Bitwarden keeps your vault automatically synced by using push notifications. For the best possible experience, please select &quot;Allow&quot; on the following prompt when asked to allow push notifications..
/// </summary> /// </summary>

View File

@@ -2820,6 +2820,9 @@ Wil u na die rekening omskakel?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2839,6 +2842,9 @@ Wil u na die rekening omskakel?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2821,6 +2821,9 @@
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>مواصلة الاتصال بالدعم؟</value> <value>مواصلة الاتصال بالدعم؟</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>هل تريد المتابعة إلى متجر التطبيقات؟</value> <value>هل تريد المتابعة إلى متجر التطبيقات؟</value>
</data> </data>
@@ -2840,6 +2843,9 @@
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>لا يمكن العثور على ما تبحث عنه؟ قم بالتواصل مع دعم Bitwarden على bitwarden.com.</value> <value>لا يمكن العثور على ما تبحث عنه؟ قم بالتواصل مع دعم Bitwarden على bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>استكشف المزيد من الميزات لحساب Bitwarden الخاص بك على تطبيق الويب.</value> <value>استكشف المزيد من الميزات لحساب Bitwarden الخاص بك على تطبيق الويب.</value>
</data> </data>

View File

@@ -156,7 +156,7 @@
<comment>The button text that allows a user to copy the login's password to their clipboard.</comment> <comment>The button text that allows a user to copy the login's password to their clipboard.</comment>
</data> </data>
<data name="CopyUsername" xml:space="preserve"> <data name="CopyUsername" xml:space="preserve">
<value>İstifadəçi adını kopyalayın</value> <value>İstifadəçi adını kopyala</value>
<comment>The button text that allows a user to copy the login's username to their clipboard.</comment> <comment>The button text that allows a user to copy the login's username to their clipboard.</comment>
</data> </data>
<data name="Credits" xml:space="preserve"> <data name="Credits" xml:space="preserve">
@@ -176,7 +176,7 @@
<comment>Confirmation alert message when deleteing something.</comment> <comment>Confirmation alert message when deleteing something.</comment>
</data> </data>
<data name="Edit" xml:space="preserve"> <data name="Edit" xml:space="preserve">
<value>Redaktə edin</value> <value>Düzəliş et</value>
</data> </data>
<data name="EditFolder" xml:space="preserve"> <data name="EditFolder" xml:space="preserve">
<value>Qovluğa düzəliş et</value> <value>Qovluğa düzəliş et</value>
@@ -349,7 +349,7 @@
<value>Göndər</value> <value>Göndər</value>
</data> </data>
<data name="Sync" xml:space="preserve"> <data name="Sync" xml:space="preserve">
<value>Eyniləşdirmə</value> <value>Sinxr</value>
<comment>The title for the sync page.</comment> <comment>The title for the sync page.</comment>
</data> </data>
<data name="ThankYou" xml:space="preserve"> <data name="ThankYou" xml:space="preserve">
@@ -416,7 +416,7 @@
<value>Tətbiq uzantısı</value> <value>Tətbiq uzantısı</value>
</data> </data>
<data name="AutofillAccessibilityDescription" xml:space="preserve"> <data name="AutofillAccessibilityDescription" xml:space="preserve">
<value>Tətbiq və veb saytda giriş məlumatlarının avto-doldurulması üçün Bitwarden əlçatımlılıq xidmətini istifadə edin.</value> <value>Tətbiqlərdə və veb giriş məlumatlarının avto-doldurulması üçün Bitwarden əlçatımlılıq xidmətini istifadə edin.</value>
</data> </data>
<data name="AutofillService" xml:space="preserve"> <data name="AutofillService" xml:space="preserve">
<value>Avto-doldurma xidməti</value> <value>Avto-doldurma xidməti</value>
@@ -465,7 +465,7 @@
<value>Elementə düzəliş et</value> <value>Elementə düzəliş et</value>
</data> </data>
<data name="EnableAutomaticSyncing" xml:space="preserve"> <data name="EnableAutomaticSyncing" xml:space="preserve">
<value>Avto-eyniləşdirməni fəallaşdır</value> <value>Avto-sinxr icazə ver</value>
</data> </data>
<data name="EnterEmailForHint" xml:space="preserve"> <data name="EnterEmailForHint" xml:space="preserve">
<value>Ana parol məsləhətini alacağınız hesabınızın e-poçt ünvanını daxil edin.</value> <value>Ana parol məsləhətini alacağınız hesabınızın e-poçt ünvanını daxil edin.</value>
@@ -523,7 +523,7 @@
<value>Digər parol idarəetmə tətbiqlərindəki elementləri cəld və toplu formada daxilə köçürün.</value> <value>Digər parol idarəetmə tətbiqlərindəki elementləri cəld və toplu formada daxilə köçürün.</value>
</data> </data>
<data name="LastSync" xml:space="preserve"> <data name="LastSync" xml:space="preserve">
<value>Son eyniləşdirmə:</value> <value>Son sinxr:</value>
</data> </data>
<data name="Length" xml:space="preserve"> <data name="Length" xml:space="preserve">
<value>Uzunluq</value> <value>Uzunluq</value>
@@ -641,7 +641,7 @@
<value>Hazırkı parolun üzərinə yazmaq istədiyinizə əminsiniz?</value> <value>Hazırkı parolun üzərinə yazmaq istədiyinizə əminsiniz?</value>
</data> </data>
<data name="PushNotificationAlert" xml:space="preserve"> <data name="PushNotificationAlert" xml:space="preserve">
<value>Bitwarden, ani bildirişləri istifadə edərək anbarınızı avtomatik eyniləşdirir. Mümkün olan ən yaxşı təcrübəni təqdim etmək üçün, sizdən ani bildirişləri fəallaşdırmağı soruşanda növbəti ekranda "İcazə ver"i seçin.</value> <value>Bitwarden, ani bildirişləri istifadə edərək anbarınızın avtomatik sinxronlaşdırılmasını təmin edir. Mümkün olan ən yaxşı təcrübəni təqdim etmək üçün, sizdən ani bildirişləri fəallaşdırmağı soruşduqda növbəti ekranda "İcazə ver"i seçin.</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">
@@ -682,17 +682,17 @@
<comment>Message shown when interacting with the server</comment> <comment>Message shown when interacting with the server</comment>
</data> </data>
<data name="Syncing" xml:space="preserve"> <data name="Syncing" xml:space="preserve">
<value>Eyniləşdirilir...</value> <value>Sinxronlaşdırılır...</value>
<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>Eyniləşdirmə tamamlandı.</value> <value>Sinxr tamamlandı</value>
</data> </data>
<data name="SyncingFailed" xml:space="preserve"> <data name="SyncingFailed" xml:space="preserve">
<value>Uğursuz eyniləşdirmə.</value> <value>Sinxr uğursuz oldu</value>
</data> </data>
<data name="SyncVaultNow" xml:space="preserve"> <data name="SyncVaultNow" xml:space="preserve">
<value>Anbarı indi eyniləşdir</value> <value>Anbarı indi sinxronlaşdır</value>
</data> </data>
<data name="TouchID" xml:space="preserve"> <data name="TouchID" xml:space="preserve">
<value>Touch ID</value> <value>Touch ID</value>
@@ -745,7 +745,7 @@
<comment>This is used for the autofill service. ex. "There are no items in your vault for twitter.com".</comment> <comment>This is used for the autofill service. ex. "There are no items in your vault for twitter.com".</comment>
</data> </data>
<data name="BitwardenAutofillServiceOverlay" xml:space="preserve"> <data name="BitwardenAutofillServiceOverlay" xml:space="preserve">
<value>Bir giriş sahəsi seçəndə və Bitwarden avto-doldurma örtüyünü görəndə, avto-doldurma xidmətini başlatmaq üçün ona toxuna bilərsiniz.</value> <value>Bir giriş xanası seçdikdə və Bitwarden avto-doldurma örtüyünü gördükdə, avto-doldurma xidmətini başlatmaq üçün buna toxuna bilərsiniz.</value>
</data> </data>
<data name="BitwardenAutofillServiceNotificationContent" xml:space="preserve"> <data name="BitwardenAutofillServiceNotificationContent" xml:space="preserve">
<value>Anbarınızdakı bir elementi avto-doldurmaq üçün bu bildirişə toxunun.</value> <value>Anbarınızdakı bir elementi avto-doldurmaq üçün bu bildirişə toxunun.</value>
@@ -1167,10 +1167,10 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Avto-doldurma əlçatımlılıq xidməti</value> <value>Avto-doldurma əlçatımlılıq xidməti</value>
</data> </data>
<data name="AutofillServiceDescription" xml:space="preserve"> <data name="AutofillServiceDescription" xml:space="preserve">
<value>Bitwarden avto-doldurma xidməti, giriş məlumatlarının, kredit kartlarının və kimlik məlumatlarının cihazınızdakı digər tətbiqlərdə doldurmasına kömək etməsi üçün Android avto-doldurma sistemini istifadə edir.</value> <value>Bitwarden avto-doldurma xidməti, giriş məlumatlarının cihazınızdakı digər tətbiqlərdə doldurmasına kömək etməsi üçün Android Avto-doldurma Çərçivəsini istifadə edir.</value>
</data> </data>
<data name="BitwardenAutofillServiceDescription" xml:space="preserve"> <data name="BitwardenAutofillServiceDescription" xml:space="preserve">
<value>Digər tətbiqlərdəki giriş məlumatlarının, kredit kartlarının və kimlik məlumatlarının doldurulması üçün Bitwarden avto-doldurma xidmətini istifadə edin.</value> <value>Giriş məlumatlarını digər tətbiqlərdə doldurmaq üçün Bitwarden avto-doldurma xidmətini istifadə edin.</value>
</data> </data>
<data name="BitwardenAutofillServiceOpenAutofillSettings" xml:space="preserve"> <data name="BitwardenAutofillServiceOpenAutofillSettings" xml:space="preserve">
<value>Avto-doldurma ayarlarını aç</value> <value>Avto-doldurma ayarlarını aç</value>
@@ -1289,7 +1289,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Avto-doldurmanı istifadə edə bilmək üçün Bitwarden tətbiqində giriş etməlisiniz.</value> <value>Avto-doldurmanı istifadə edə bilmək üçün Bitwarden tətbiqində giriş etməlisiniz.</value>
</data> </data>
<data name="AutofillSetup" xml:space="preserve"> <data name="AutofillSetup" xml:space="preserve">
<value>Tətbiqlərdə və veb saytlarda giriş edərkən giriş etmə məlumatlarınıza klaviaturadan asanlıqla müraciət edə bilərsiniz.</value> <value>Tətbiqlərdə və veb saytlarda giriş edərkən giriş məlumatlarınıza klaviaturadan asanlıqla müraciət edə bilərsiniz.</value>
</data> </data>
<data name="AutofillSetup2" xml:space="preserve"> <data name="AutofillSetup2" xml:space="preserve">
<value>İstifadə etməyi düşünmürsünüzsə, digər Avto-doldurma tətbiqlərini Ayarlarda sıradan çıxartmağı tövsiyə edirik.</value> <value>İstifadə etməyi düşünmürsünüzsə, digər Avto-doldurma tətbiqlərini Ayarlarda sıradan çıxartmağı tövsiyə edirik.</value>
@@ -1369,10 +1369,10 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Növlər</value> <value>Növlər</value>
</data> </data>
<data name="NoPasswordsToList" xml:space="preserve"> <data name="NoPasswordsToList" xml:space="preserve">
<value>Siyahılanacaq parol yoxdur.</value> <value>Sadalanacaq parol yoxdur.</value>
</data> </data>
<data name="NoItemsToList" xml:space="preserve"> <data name="NoItemsToList" xml:space="preserve">
<value>Siyahılanacaq heç bir element yoxdur.</value> <value>Sadalanacaq heç bir element yoxdur.</value>
</data> </data>
<data name="SearchCollection" xml:space="preserve"> <data name="SearchCollection" xml:space="preserve">
<value>Kolleksiya axtar</value> <value>Kolleksiya axtar</value>
@@ -1406,7 +1406,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Bu elementin sahibi kimdir?</value> <value>Bu elementin sahibi kimdir?</value>
</data> </data>
<data name="NoCollectionsToList" xml:space="preserve"> <data name="NoCollectionsToList" xml:space="preserve">
<value>Siyahılanacaq heç bir kolleksiya yoxdur.</value> <value>Sadalanacaq heç bir kolleksiya yoxdur.</value>
</data> </data>
<data name="MovedItemToOrg" xml:space="preserve"> <data name="MovedItemToOrg" xml:space="preserve">
<value>{0}, {1} ünvanına daşındı.</value> <value>{0}, {1} ünvanına daşındı.</value>
@@ -1428,7 +1428,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Təşkilata daşı</value> <value>Təşkilata daşı</value>
</data> </data>
<data name="NoOrgsToList" xml:space="preserve"> <data name="NoOrgsToList" xml:space="preserve">
<value>Siyahılanacaq heç bir təşkilat yoxdur.</value> <value>Sadalanacaq heç bir təşkilat yoxdur.</value>
</data> </data>
<data name="MoveToOrgDesc" xml:space="preserve"> <data name="MoveToOrgDesc" xml:space="preserve">
<value>Bu elementi daşımaq istədiyiniz təşkilatı seçin. Bir təşkilata daşımaq, elementin sahibliyini də həmin təşkilata daşıyacaq. Daşıdıqdan sonra bu elementə birbaşa sahibliyiniz olmayacaq.</value> <value>Bu elementi daşımaq istədiyiniz təşkilatı seçin. Bir təşkilata daşımaq, elementin sahibliyini də həmin təşkilata daşıyacaq. Daşıdıqdan sonra bu elementə birbaşa sahibliyiniz olmayacaq.</value>
@@ -1451,7 +1451,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<comment>Short for "Password Generator"</comment> <comment>Short for "Password Generator"</comment>
</data> </data>
<data name="NoFoldersToList" xml:space="preserve"> <data name="NoFoldersToList" xml:space="preserve">
<value>Siyahılanacaq heç bir qovluq yoxdur.</value> <value>Sadalanacaq heç bir qovluq yoxdur.</value>
</data> </data>
<data name="FingerprintPhrase" xml:space="preserve"> <data name="FingerprintPhrase" xml:space="preserve">
<value>Barmaq izi ifadəsi</value> <value>Barmaq izi ifadəsi</value>
@@ -1747,10 +1747,10 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Ana parolun doğrulanması gözlənildiyi üçün bu hesab üzrə avto-doldurma biometrik kilid açma sıradan çıxarıldı.</value> <value>Ana parolun doğrulanması gözlənildiyi üçün bu hesab üzrə avto-doldurma biometrik kilid açma sıradan çıxarıldı.</value>
</data> </data>
<data name="EnableSyncOnRefresh" xml:space="preserve"> <data name="EnableSyncOnRefresh" xml:space="preserve">
<value>Təzələmə əsnasında eyniləşdirməni fəallaşdır</value> <value>Təzələmə zamanı sinxr icazə ver</value>
</data> </data>
<data name="EnableSyncOnRefreshDescription" xml:space="preserve"> <data name="EnableSyncOnRefreshDescription" xml:space="preserve">
<value>Barmağınızla aşağı çəkəndə anbarı eyniləşdir</value> <value>Barmağınızla aşağı çəkdikdə anbarı sinxronlaşdır.</value>
</data> </data>
<data name="LogInSso" xml:space="preserve"> <data name="LogInSso" xml:space="preserve">
<value>Müəssisə üçün tək daxil olma</value> <value>Müəssisə üçün tək daxil olma</value>
@@ -1828,10 +1828,10 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Əlçatımlılığı istifadə et</value> <value>Əlçatımlılığı istifadə et</value>
</data> </data>
<data name="AccessibilityDescription" xml:space="preserve"> <data name="AccessibilityDescription" xml:space="preserve">
<value>Saytda və tətbiqlərdə giriş məlumatlarınızın avto-doldurulması üçün Bitwarden əlçatımlılıq xidmətini istifadə edə bilərsiniz. Fəal olanda, giriş məlumatlarını daxil edərkən açılan pəncərə görünəcək.</value> <value>Saytda və vebdə giriş məlumatlarınızı avto-doldurmaq üçün Bitwarden Əlçatımlılıq Xidmətini istifadə edin. Qurulanda, giriş xanalarını seçərkən açılan pəncərə göstərəcəyik.</value>
</data> </data>
<data name="AccessibilityDescription2" xml:space="preserve"> <data name="AccessibilityDescription2" xml:space="preserve">
<value>Saytda və tətbiqlərdə giriş məlumatlarınızın avto-doldurulması üçün Bitwarden əlçatımlılıq xidmətini istifadə edə bilərsiniz. ("Üzərində göstər" seçiminin fəal olması lazımdır)</value> <value>Saytda və vebdə giriş məlumatlarınızı avto-doldurmaq üçün Bitwarden Əlçatımlılıq Xidmətini istifadə edin. ("Üzərində göstər" seçimiıq olmalıdır)</value>
</data> </data>
<data name="AccessibilityDescription3" xml:space="preserve"> <data name="AccessibilityDescription3" xml:space="preserve">
<value>Avto-doldurma cəld əməliyyat qutusunu istifadə etmək üçün Bitwarden əlçatımlılıq xidmətini istifadə edin və/və ya "Üzərində göstər"i (əgər fəaldırsa) istifadə edərək açılan bir pəncərə göstərə bilərsiniz.</value> <value>Avto-doldurma cəld əməliyyat qutusunu istifadə etmək üçün Bitwarden əlçatımlılıq xidmətini istifadə edin və/və ya "Üzərində göstər"i (əgər fəaldırsa) istifadə edərək açılan bir pəncərə göstərə bilərsiniz.</value>
@@ -1843,13 +1843,13 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>"Üzərində göstər"i istifadə edin</value> <value>"Üzərində göstər"i istifadə edin</value>
</data> </data>
<data name="DrawOverDescription" xml:space="preserve"> <data name="DrawOverDescription" xml:space="preserve">
<value>Fəal olsa, giriş məlumatları daxil ediləndə Bitwarden əlçatımlılıq xidmətinəılan pəncərə görüntüləməsinə icazə verir.</value> <value>Giriş xanalarını seçdikdə Bitwarden Əlçatımlılıq Xidmətininılan pəncərə göstərməsinə icazə verir.</value>
</data> </data>
<data name="DrawOverDescription2" xml:space="preserve"> <data name="DrawOverDescription2" xml:space="preserve">
<value>Fəal olsa, giriş məlumatlarının avto-doldurmasına köməkçi olması üçün giriş sahələri seçiləndə Bitwarden əlçatımlılıq xidmətiılan bir pəncərə görüntüləyəcək.</value> <value>İşə salındıqda Bitwarden Əlçatımlılıq Xidməti, giriş məlumatlarınızın avto-doldurmasına kömək etmək üçün giriş xanaları seçildikdəılan pəncərə göstərəcək.</value>
</data> </data>
<data name="DrawOverDescription3" xml:space="preserve"> <data name="DrawOverDescription3" xml:space="preserve">
<value>Fəal olsa, əlçatımlılıq, Android-in avto-doldurma sistemini dəstəkləməyən köhnə tətbiqlər üçün Avto-doldurma xidmətini təqlid etməsi üçün açılan bir pəncərə göstərəcək.</value> <value>Fəal olsa, əlçatımlılıq, Android Avto-doldurma Çərçivəsini dəstəkləməyən köhnə tətbiqlər Avto-doldurma Xidmətini təqlid etməsi üçün açılan bir pəncərə göstərəcək.</value>
</data> </data>
<data name="PersonalOwnershipSubmitError" xml:space="preserve"> <data name="PersonalOwnershipSubmitError" xml:space="preserve">
<value>Müəssisə Siyasətinə görə, elementləri şəxsi anbarınızda saxlamağınız məhdudlaşdırılıb. Sahiblik seçimini təşkilat olaraq dəyişdirin və mövcud kolleksiyalar arasından seçim edin.</value> <value>Müəssisə Siyasətinə görə, elementləri şəxsi anbarınızda saxlamağınız məhdudlaşdırılıb. Sahiblik seçimini təşkilat olaraq dəyişdirin və mövcud kolleksiyalar arasından seçim edin.</value>
@@ -2464,7 +2464,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Əlçatımlılıq Xidməti açıqlaması</value> <value>Əlçatımlılıq Xidməti açıqlaması</value>
</data> </data>
<data name="AccessibilityDisclosureText" xml:space="preserve"> <data name="AccessibilityDisclosureText" xml:space="preserve">
<value>Bitwarden, tətbiqlərdə və veb saytlarda giriş sahələrini axtarmaq üçün Əlçatımlılıq Xidmətini istifadə edir, daha sonra tətbiq və ya sayt üçün uyuşma tapdıqda istifadəçi adı və parolun daxil edilməsi üçün müvafiq sahə kimliklərini yaradır. Xidmət tərəfindən bizə təqdim edilən məlumatların heç birini saxlamırıq, kimlik məlumatlarının daxil edilməsindən kənar ekrandakı hər hansısa elementə nəzarət etməyə cəhd etmirik.</value> <value>Bitwarden, tətbiqlərdə və veb saytlarda giriş xanalarını axtarmaq üçün Əlçatımlılıq Xidmətini istifadə edir, daha sonra tətbiq və ya sayt üçün uyuşma tapdıqda istifadəçi adı və parolun daxil edilməsi üçün müvafiq sahə kimliklərini yaradır. Xidmət tərəfindən bizə təqdim edilən məlumatların heç birini saxlamırıq, kimlik məlumatlarının daxil edilməsindən kənar ekrandakı hər hansısa elementə nəzarət etməyə cəhd etmirik.</value>
</data> </data>
<data name="Accept" xml:space="preserve"> <data name="Accept" xml:space="preserve">
<value>Qəbul et</value> <value>Qəbul et</value>
@@ -2801,7 +2801,7 @@ Bu hesaba keçmək istəyirsiniz?</value>
<value>Android Avto-doldurma Çərçivəsi, giriş məlumatlarını cihazınızdakı digər tətbiqlərə doldurmağa kömək etmək üçün istifadə olunur.</value> <value>Android Avto-doldurma Çərçivəsi, giriş məlumatlarını cihazınızdakı digər tətbiqlərə doldurmağa kömək etmək üçün istifadə olunur.</value>
</data> </data>
<data name="UseInlineAutofillExplanationLong" xml:space="preserve"> <data name="UseInlineAutofillExplanationLong" xml:space="preserve">
<value>Seçdiyiniz klaviatura dəstəkləyirsə sətir daxili avto-doldurmani istifadə edin. Əks halda, ilkin örtük istifadə edin.</value> <value>Seçdiyiniz klaviatura dəstəkləyirsə sətir daxili avto-doldurmanı istifadə edin. Əks halda, ilkin örtük istifadə edin.</value>
</data> </data>
<data name="AdditionalOptions" xml:space="preserve"> <data name="AdditionalOptions" xml:space="preserve">
<value>Əlavə seçimlər</value> <value>Əlavə seçimlər</value>
@@ -2819,6 +2819,9 @@ Bu hesaba keçmək istəyirsiniz?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Dəstək komandası ilə əlaqə qurmağa davam edilsin?</value> <value>Dəstək komandası ilə əlaqə qurmağa davam edilsin?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Gizlilik Siyasətinə davam edirsiniz?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Tətbiq mağazası ilə davam edilsin?</value> <value>Tətbiq mağazası ilə davam edilsin?</value>
</data> </data>
@@ -2838,6 +2841,9 @@ Bu hesaba keçmək istəyirsiniz?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Axtardığınızı tapa bilmirsiniz? bitwarden.com üzərindən Bitwarden dəstəyinə müraciət edin.</value> <value>Axtardığınızı tapa bilmirsiniz? bitwarden.com üzərindən Bitwarden dəstəyinə müraciət edin.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>bitwarden.com saytında gizlilik siyasətimizi nəzərdən keçirin.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Veb tətbiqində Bitwarden hesabınızın daha çox özəlliyini kəşf edin.</value> <value>Veb tətbiqində Bitwarden hesabınızın daha çox özəlliyini kəşf edin.</value>
</data> </data>

View File

@@ -2820,6 +2820,9 @@
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2839,6 +2842,9 @@
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2820,6 +2820,9 @@
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Продължаване към връзка с поддръжката?</value> <value>Продължаване към връзка с поддръжката?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Продължаване към Политиката за поверителност?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Продължаване към магазина за приложения?</value> <value>Продължаване към магазина за приложения?</value>
</data> </data>
@@ -2839,6 +2842,9 @@
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Не намирате това, което търсите? Свържете се с поддръжката на Битуорден на bitwarden.com.</value> <value>Не намирате това, което търсите? Свържете се с поддръжката на Битуорден на bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Прегледайте нашата Политика за поверителност на bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Разгледайте още от възможностите на регистрацията си в Битуорден в уеб приложението.</value> <value>Разгледайте още от възможностите на регистрацията си в Битуорден в уеб приложението.</value>
</data> </data>

View File

@@ -2821,6 +2821,9 @@ Do you want to switch to this account?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2840,6 +2843,9 @@ Do you want to switch to this account?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2819,6 +2819,9 @@ Skeniranje će biti izvršeno automatski.</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2838,6 +2841,9 @@ Skeniranje će biti izvršeno automatski.</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2820,6 +2820,9 @@ Voleu canviar a aquest compte?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Voleu continuar per contactar amb l'assistència?</value> <value>Voleu continuar per contactar amb l'assistència?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Voleu continuar amb la política de privadesa?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Voleu continuar cap a l'app store?</value> <value>Voleu continuar cap a l'app store?</value>
</data> </data>
@@ -2839,6 +2842,9 @@ Voleu canviar a aquest compte?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>No trobeu el que esteu buscant? Poseu-vos en contacte amb l'assistència de Bitwarden a bitwarden.com.</value> <value>No trobeu el que esteu buscant? Poseu-vos en contacte amb l'assistència de Bitwarden a bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Consulteu la nostra política de privadesa a bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Exploreu més característiques del vostre compte Bitwarden a l'aplicació web.</value> <value>Exploreu més característiques del vostre compte Bitwarden a l'aplicació web.</value>
</data> </data>

View File

@@ -2819,6 +2819,9 @@ Chcete se přepnout na tento účet?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Pokračovat v kontaktování podpory?</value> <value>Pokračovat v kontaktování podpory?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Pokračovat na Zásady ochrany osobních údajů?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Pokračovat do obchodu s aplikacemi?</value> <value>Pokračovat do obchodu s aplikacemi?</value>
</data> </data>
@@ -2838,6 +2841,9 @@ Chcete se přepnout na tento účet?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Nenašli jste to, co jste hledali? Na bitwarden.com získejte podporu.</value> <value>Nenašli jste to, co jste hledali? Na bitwarden.com získejte podporu.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Podívejte se na naše Zásady ochrany osobních údajů na bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Prozkoumejte další funkce Vašeho účtu Bitwarden ve webové aplikaci.</value> <value>Prozkoumejte další funkce Vašeho účtu Bitwarden ve webové aplikaci.</value>
</data> </data>

View File

@@ -144,7 +144,7 @@
<comment>App name. Shouldn't ever change.</comment> <comment>App name. Shouldn't ever change.</comment>
</data> </data>
<data name="Cancel" xml:space="preserve"> <data name="Cancel" xml:space="preserve">
<value>Cancel</value> <value>Yn ôl</value>
<comment>Cancel an operation.</comment> <comment>Cancel an operation.</comment>
</data> </data>
<data name="Copy" xml:space="preserve"> <data name="Copy" xml:space="preserve">
@@ -152,11 +152,11 @@
<comment>Copy some value to your clipboard.</comment> <comment>Copy some value to your clipboard.</comment>
</data> </data>
<data name="CopyPassword" xml:space="preserve"> <data name="CopyPassword" xml:space="preserve">
<value>Copy password</value> <value>Copïo'r cyfrinair</value>
<comment>The button text that allows a user to copy the login's password to their clipboard.</comment> <comment>The button text that allows a user to copy the login's password to their clipboard.</comment>
</data> </data>
<data name="CopyUsername" xml:space="preserve"> <data name="CopyUsername" xml:space="preserve">
<value>Copy username</value> <value>Copïo'r enw defnyddiwr</value>
<comment>The button text that allows a user to copy the login's username to their clipboard.</comment> <comment>The button text that allows a user to copy the login's username to their clipboard.</comment>
</data> </data>
<data name="Credits" xml:space="preserve"> <data name="Credits" xml:space="preserve">
@@ -265,7 +265,7 @@
<comment>The login button text (verb).</comment> <comment>The login button text (verb).</comment>
</data> </data>
<data name="LogInNoun" xml:space="preserve"> <data name="LogInNoun" xml:space="preserve">
<value>Login</value> <value>Mewngofnodi</value>
<comment>Title for login page. (noun)</comment> <comment>Title for login page. (noun)</comment>
</data> </data>
<data name="LogOut" xml:space="preserve"> <data name="LogOut" xml:space="preserve">
@@ -282,7 +282,7 @@
<value>Are you sure you want to remove this account?</value> <value>Are you sure you want to remove this account?</value>
</data> </data>
<data name="AccountAlreadyAdded" xml:space="preserve"> <data name="AccountAlreadyAdded" xml:space="preserve">
<value>Account already added</value> <value>Wedi'i ychwanegu eisoes</value>
</data> </data>
<data name="SwitchToAlreadyAddedAccountConfirmation" xml:space="preserve"> <data name="SwitchToAlreadyAddedAccountConfirmation" xml:space="preserve">
<value>Would you like to switch to it now?</value> <value>Would you like to switch to it now?</value>
@@ -308,7 +308,7 @@
<comment>Label for an entity name.</comment> <comment>Label for an entity name.</comment>
</data> </data>
<data name="No" xml:space="preserve"> <data name="No" xml:space="preserve">
<value>No</value> <value>Na</value>
</data> </data>
<data name="Notes" xml:space="preserve"> <data name="Notes" xml:space="preserve">
<value>Nodiadau</value> <value>Nodiadau</value>
@@ -327,7 +327,7 @@
<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>Move</value> <value>Symud</value>
</data> </data>
<data name="Saving" xml:space="preserve"> <data name="Saving" xml:space="preserve">
<value>Yn cadw...</value> <value>Yn cadw...</value>
@@ -391,7 +391,7 @@
<value>Fersiwn</value> <value>Fersiwn</value>
</data> </data>
<data name="View" xml:space="preserve"> <data name="View" xml:space="preserve">
<value>View</value> <value>Gweld</value>
</data> </data>
<data name="VisitOurWebsite" xml:space="preserve"> <data name="VisitOurWebsite" xml:space="preserve">
<value>Visit our website</value> <value>Visit our website</value>
@@ -401,7 +401,7 @@
<comment>Label for a website.</comment> <comment>Label for a website.</comment>
</data> </data>
<data name="Yes" xml:space="preserve"> <data name="Yes" xml:space="preserve">
<value>Yes</value> <value>Ydw</value>
</data> </data>
<data name="Account" xml:space="preserve"> <data name="Account" xml:space="preserve">
<value>Cyfrif</value> <value>Cyfrif</value>
@@ -455,7 +455,7 @@
<value>Parhau</value> <value>Parhau</value>
</data> </data>
<data name="CreateAccount" xml:space="preserve"> <data name="CreateAccount" xml:space="preserve">
<value>Creu cyfrif</value> <value>Crëwch gyfrif</value>
</data> </data>
<data name="CreatingAccount" xml:space="preserve"> <data name="CreatingAccount" xml:space="preserve">
<value>Wrthi'n creu cyfrif...</value> <value>Wrthi'n creu cyfrif...</value>
@@ -484,13 +484,13 @@
<comment>Safari is the name of apple's web browser</comment> <comment>Safari is the name of apple's web browser</comment>
</data> </data>
<data name="ExtensionInstantAccess" xml:space="preserve"> <data name="ExtensionInstantAccess" xml:space="preserve">
<value>Get instant access to your passwords!</value> <value>Mynnwch fynediad i'ch cyfrineiriau ar unwaith!</value>
</data> </data>
<data name="ExtensionReady" xml:space="preserve"> <data name="ExtensionReady" xml:space="preserve">
<value>Rydych chi'n barod i fewngofnodi!</value> <value>Rydych chi'n barod i fewngofnodi!</value>
</data> </data>
<data name="ExtensionSetup" xml:space="preserve"> <data name="ExtensionSetup" xml:space="preserve">
<value>Your logins are now easily accessible from Safari, Chrome, and other supported apps.</value> <value>Mae eich manylion mewngofnodi bellach yn hawdd i'w canfod o Safari, Chrome, ac apiau eraill.</value>
</data> </data>
<data name="ExtensionSetup2" xml:space="preserve"> <data name="ExtensionSetup2" xml:space="preserve">
<value>In Safari and Chrome, find Bitwarden using the share icon (hint: scroll to the right on the bottom row of the share menu).</value> <value>In Safari and Chrome, find Bitwarden using the share icon (hint: scroll to the right on the bottom row of the share menu).</value>
@@ -502,7 +502,7 @@
<value>To turn on Bitwarden in Safari and other apps, tap the "more" icon on the bottom row of the menu.</value> <value>To turn on Bitwarden in Safari and other apps, tap the "more" icon on the bottom row of the menu.</value>
</data> </data>
<data name="Favorite" xml:space="preserve"> <data name="Favorite" xml:space="preserve">
<value>Favorite</value> <value>Ffefryn</value>
</data> </data>
<data name="Fingerprint" xml:space="preserve"> <data name="Fingerprint" xml:space="preserve">
<value>Ôl bys</value> <value>Ôl bys</value>
@@ -511,7 +511,7 @@
<value>Cynhyrchu cyfrinair</value> <value>Cynhyrchu cyfrinair</value>
</data> </data>
<data name="GetPasswordHint" xml:space="preserve"> <data name="GetPasswordHint" xml:space="preserve">
<value>Get your master password hint</value> <value>Anfon awgrym o'ch prif gyfrinair</value>
</data> </data>
<data name="ImportItems" xml:space="preserve"> <data name="ImportItems" xml:space="preserve">
<value>Mewnforio eitemau</value> <value>Mewnforio eitemau</value>
@@ -572,27 +572,27 @@
<value>The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it.</value> <value>The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it.</value>
</data> </data>
<data name="MasterPasswordHint" xml:space="preserve"> <data name="MasterPasswordHint" xml:space="preserve">
<value>Master password hint (optional)</value> <value>Awgrym o'ch prif gyfrinair (dewisol)</value>
</data> </data>
<data name="MasterPasswordHintDescription" xml:space="preserve"> <data name="MasterPasswordHintDescription" xml:space="preserve">
<value>Gall awgrym o'ch prif gyfrinair eich helpu i'w gofio os ydych chi'n ei anghofio.</value> <value>Gall awgrym o'ch prif gyfrinair eich helpu i'w gofio os ydych chi'n ei anghofio.</value>
</data> </data>
<data name="MasterPasswordLengthValMessageX" xml:space="preserve"> <data name="MasterPasswordLengthValMessageX" xml:space="preserve">
<value>Master password must be at least {0} characters long.</value> <value>Rhaid i'ch prif gyfrinair gynnwys o leiaf {0} nod.</value>
</data> </data>
<data name="MinNumbers" xml:space="preserve"> <data name="MinNumbers" xml:space="preserve">
<value>Isafswm rhifau</value> <value>Isafswm rhifau</value>
<comment>Minimum numeric characters for password generator settings</comment> <comment>Minimum numeric characters for password generator settings</comment>
</data> </data>
<data name="MinSpecial" xml:space="preserve"> <data name="MinSpecial" xml:space="preserve">
<value>Isafswm arbennig</value> <value>Isafswm nodau arbennig</value>
<comment>Minimum special characters for password generator settings</comment> <comment>Minimum special characters for password generator settings</comment>
</data> </data>
<data name="MoreSettings" xml:space="preserve"> <data name="MoreSettings" xml:space="preserve">
<value>Mwy o osodiadau</value> <value>Mwy o osodiadau</value>
</data> </data>
<data name="MustLogInMainApp" xml:space="preserve"> <data name="MustLogInMainApp" xml:space="preserve">
<value>You must log into the main Bitwarden app before you can use the extension.</value> <value>Rhaid i chi fewngofnodi i brif ap Bitwarden cyn defnyddio'r estyniad.</value>
</data> </data>
<data name="Never" xml:space="preserve"> <data name="Never" xml:space="preserve">
<value>byth</value> <value>byth</value>
@@ -610,7 +610,7 @@
<value>There are no items in your vault for this website/app. Tap to add one.</value> <value>There are no items in your vault for this website/app. Tap to add one.</value>
</data> </data>
<data name="NoUsernamePasswordConfigured" xml:space="preserve"> <data name="NoUsernamePasswordConfigured" xml:space="preserve">
<value>This login does not have a username or password configured.</value> <value>Does dim enw defnyddiwr na chyfrinair i'r manylyn mewngofnodi hwn.</value>
</data> </data>
<data name="OkGotIt" xml:space="preserve"> <data name="OkGotIt" xml:space="preserve">
<value>Iawn, deall!</value> <value>Iawn, deall!</value>
@@ -623,7 +623,7 @@
<value>Dewisiadau</value> <value>Dewisiadau</value>
</data> </data>
<data name="Other" xml:space="preserve"> <data name="Other" xml:space="preserve">
<value>Other</value> <value>Gosodiadau eraill</value>
</data> </data>
<data name="PasswordGenerated" xml:space="preserve"> <data name="PasswordGenerated" xml:space="preserve">
<value>Password generated</value> <value>Password generated</value>
@@ -632,7 +632,7 @@
<value>Cynhyrchydd cyfrineiriau</value> <value>Cynhyrchydd cyfrineiriau</value>
</data> </data>
<data name="PasswordHint" xml:space="preserve"> <data name="PasswordHint" xml:space="preserve">
<value>Password hint</value> <value>Awgrym o'r cyfrinair</value>
</data> </data>
<data name="PasswordHintAlert" xml:space="preserve"> <data name="PasswordHintAlert" xml:space="preserve">
<value>Rydym ni wedi anfon ebost atoch gydag awgrym ar gyfer eich prif gyfrinair.</value> <value>Rydym ni wedi anfon ebost atoch gydag awgrym ar gyfer eich prif gyfrinair.</value>
@@ -654,7 +654,7 @@
<value>Ailgynhyrchu cyfrinair</value> <value>Ailgynhyrchu cyfrinair</value>
</data> </data>
<data name="RetypeMasterPassword" xml:space="preserve"> <data name="RetypeMasterPassword" xml:space="preserve">
<value>Re-type master password</value> <value>Aildeipio'r prif gyfrinair</value>
</data> </data>
<data name="SearchVault" xml:space="preserve"> <data name="SearchVault" xml:space="preserve">
<value>Chwilio'r gell</value> <value>Chwilio'r gell</value>
@@ -672,7 +672,7 @@
<value>Rhowch god PIN 4 nod i'w ddefnyddio i ddatgloi'r ap.</value> <value>Rhowch god PIN 4 nod i'w ddefnyddio i ddatgloi'r ap.</value>
</data> </data>
<data name="ItemInformation" xml:space="preserve"> <data name="ItemInformation" xml:space="preserve">
<value>Item information</value> <value>Gwybodaeth am yr eitem</value>
</data> </data>
<data name="ItemUpdated" xml:space="preserve"> <data name="ItemUpdated" xml:space="preserve">
<value>Eitem wedi'i chadw</value> <value>Eitem wedi'i chadw</value>
@@ -699,7 +699,7 @@
<comment>What Apple calls their fingerprint reader.</comment> <comment>What Apple calls their fingerprint reader.</comment>
</data> </data>
<data name="TwoStepLogin" xml:space="preserve"> <data name="TwoStepLogin" xml:space="preserve">
<value>Two-step login</value> <value>Mewngofnodi dau agm</value>
</data> </data>
<data name="UnlockWith" xml:space="preserve"> <data name="UnlockWith" xml:space="preserve">
<value>Datgloi â {0}</value> <value>Datgloi â {0}</value>
@@ -715,7 +715,7 @@
<value>Verification code</value> <value>Verification code</value>
</data> </data>
<data name="ViewItem" xml:space="preserve"> <data name="ViewItem" xml:space="preserve">
<value>View item</value> <value>Gweld yr eitem</value>
</data> </data>
<data name="WebVault" xml:space="preserve"> <data name="WebVault" xml:space="preserve">
<value>Cell we Bitwarden</value> <value>Cell we Bitwarden</value>
@@ -837,10 +837,10 @@
<comment>For 2FA</comment> <comment>For 2FA</comment>
</data> </data>
<data name="TwoStepLoginOptions" xml:space="preserve"> <data name="TwoStepLoginOptions" xml:space="preserve">
<value>Two-step login options</value> <value>Dewisiadau mewngofnodi dau gam</value>
</data> </data>
<data name="UseAnotherTwoStepMethod" xml:space="preserve"> <data name="UseAnotherTwoStepMethod" xml:space="preserve">
<value>Use another two-step login method</value> <value>Defnyddio dull mewngofnodi dau gam arall</value>
</data> </data>
<data name="VerificationEmailNotSent" xml:space="preserve"> <data name="VerificationEmailNotSent" xml:space="preserve">
<value>Could not send verification email. Try again.</value> <value>Could not send verification email. Try again.</value>
@@ -1005,10 +1005,10 @@ Scanning will happen automatically.</value>
<value>Cerdyn</value> <value>Cerdyn</value>
</data> </data>
<data name="TypeIdentity" xml:space="preserve"> <data name="TypeIdentity" xml:space="preserve">
<value>Hunaniaeth</value> <value>Eitem hunaniaeth</value>
</data> </data>
<data name="TypeLogin" xml:space="preserve"> <data name="TypeLogin" xml:space="preserve">
<value>Login</value> <value>Manylyn mewngofnodi</value>
</data> </data>
<data name="TypeSecureNote" xml:space="preserve"> <data name="TypeSecureNote" xml:space="preserve">
<value>Nodyn diogel</value> <value>Nodyn diogel</value>
@@ -1083,10 +1083,10 @@ Scanning will happen automatically.</value>
<value>Mawrth</value> <value>Mawrth</value>
</data> </data>
<data name="May" xml:space="preserve"> <data name="May" xml:space="preserve">
<value>May</value> <value>Mai</value>
</data> </data>
<data name="MiddleName" xml:space="preserve"> <data name="MiddleName" xml:space="preserve">
<value>Middle name</value> <value>Enw canol</value>
</data> </data>
<data name="Mr" xml:space="preserve"> <data name="Mr" xml:space="preserve">
<value>Mr</value> <value>Mr</value>
@@ -1104,13 +1104,13 @@ Scanning will happen automatically.</value>
<value>Tachwedd</value> <value>Tachwedd</value>
</data> </data>
<data name="October" xml:space="preserve"> <data name="October" xml:space="preserve">
<value>October</value> <value>Hydref</value>
</data> </data>
<data name="PassportNumber" xml:space="preserve"> <data name="PassportNumber" xml:space="preserve">
<value>Rhif pasbort</value> <value>Rhif pasbort</value>
</data> </data>
<data name="Phone" xml:space="preserve"> <data name="Phone" xml:space="preserve">
<value>Phone</value> <value>Ffôn</value>
</data> </data>
<data name="September" xml:space="preserve"> <data name="September" xml:space="preserve">
<value>Medi</value> <value>Medi</value>
@@ -1137,7 +1137,7 @@ Scanning will happen automatically.</value>
<value>Dangos eiconau gwefannau</value> <value>Dangos eiconau gwefannau</value>
</data> </data>
<data name="ShowWebsiteIconsDescription" xml:space="preserve"> <data name="ShowWebsiteIconsDescription" xml:space="preserve">
<value>Show a recognizable image next to each login.</value> <value>Dangos delwedd adnabyddadwy wrth ymyl pob eitem.</value>
</data> </data>
<data name="IconsUrl" xml:space="preserve"> <data name="IconsUrl" xml:space="preserve">
<value>Icons server URL</value> <value>Icons server URL</value>
@@ -1158,10 +1158,10 @@ Scanning will happen automatically.</value>
<value>There are no items in this collection.</value> <value>There are no items in this collection.</value>
</data> </data>
<data name="NoItemsFolder" xml:space="preserve"> <data name="NoItemsFolder" xml:space="preserve">
<value>There are no items in this folder.</value> <value>Does dim eitemau yn y ffolder hon.</value>
</data> </data>
<data name="NoItemsTrash" xml:space="preserve"> <data name="NoItemsTrash" xml:space="preserve">
<value>There are no items in the trash.</value> <value>Does dim eitemau yn y bin sbwriel.</value>
</data> </data>
<data name="AutofillAccessibilityService" xml:space="preserve"> <data name="AutofillAccessibilityService" xml:space="preserve">
<value>Auto-fill Accessibility Service</value> <value>Auto-fill Accessibility Service</value>
@@ -1266,7 +1266,7 @@ Scanning will happen automatically.</value>
<value>Hold your Yubikey near the top of the device.</value> <value>Hold your Yubikey near the top of the device.</value>
</data> </data>
<data name="TryAgain" xml:space="preserve"> <data name="TryAgain" xml:space="preserve">
<value>Try again</value> <value>Ceisio eto</value>
</data> </data>
<data name="YubiKeyInstructionIos" xml:space="preserve"> <data name="YubiKeyInstructionIos" xml:space="preserve">
<value>To continue, hold your YubiKey NEO against the back of the device.</value> <value>To continue, hold your YubiKey NEO against the back of the device.</value>
@@ -1351,10 +1351,10 @@ Scanning will happen automatically.</value>
<value>Gwirio a ydy'r cyfrinair wedi'i ddatgelu.</value> <value>Gwirio a ydy'r cyfrinair wedi'i ddatgelu.</value>
</data> </data>
<data name="PasswordExposed" xml:space="preserve"> <data name="PasswordExposed" xml:space="preserve">
<value>Mae'r cyfrinair hwn wedi cael ei ddatgelu {0} o weithiau mewn achosion o dorri data. Dylech chi ei newid.</value> <value>Mae'r cyfrinair hwn wedi cael ei ddatgelu {0} o weithiau mewn achosion o ddatgelu data. Dylech chi ei newid.</value>
</data> </data>
<data name="PasswordSafe" xml:space="preserve"> <data name="PasswordSafe" xml:space="preserve">
<value>This password was not found in any known data breaches. It should be safe to use.</value> <value>Chafodd y cyfrinair hwn mo'i ganfod mewn unrhyw achos hysbys o ddatgelu data. Dylai fod yn iawn i'w ddefnyddio.</value>
</data> </data>
<data name="IdentityName" xml:space="preserve"> <data name="IdentityName" xml:space="preserve">
<value>Identity name</value> <value>Identity name</value>
@@ -1366,13 +1366,13 @@ Scanning will happen automatically.</value>
<value>Password history</value> <value>Password history</value>
</data> </data>
<data name="Types" xml:space="preserve"> <data name="Types" xml:space="preserve">
<value>Types</value> <value>Mathau</value>
</data> </data>
<data name="NoPasswordsToList" xml:space="preserve"> <data name="NoPasswordsToList" xml:space="preserve">
<value>No passwords to list.</value> <value>Dim cyfrineiriau i'w rhestru.</value>
</data> </data>
<data name="NoItemsToList" xml:space="preserve"> <data name="NoItemsToList" xml:space="preserve">
<value>There are no items to list.</value> <value>Does dim eitemau i'w rhestu.</value>
</data> </data>
<data name="SearchCollection" xml:space="preserve"> <data name="SearchCollection" xml:space="preserve">
<value>Search collection</value> <value>Search collection</value>
@@ -1384,7 +1384,7 @@ Scanning will happen automatically.</value>
<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>Chwilio {0}</value>
<comment>ex: Search Logins</comment> <comment>ex: Search Logins</comment>
</data> </data>
<data name="Type" xml:space="preserve"> <data name="Type" xml:space="preserve">
@@ -1451,7 +1451,7 @@ Scanning will happen automatically.</value>
<comment>Short for "Password Generator"</comment> <comment>Short for "Password Generator"</comment>
</data> </data>
<data name="NoFoldersToList" xml:space="preserve"> <data name="NoFoldersToList" xml:space="preserve">
<value>There are no folders to list.</value> <value>Does dim ffolderi i'w rhestru.</value>
</data> </data>
<data name="FingerprintPhrase" xml:space="preserve"> <data name="FingerprintPhrase" xml:space="preserve">
<value>Fingerprint phrase</value> <value>Fingerprint phrase</value>
@@ -1522,11 +1522,11 @@ Scanning will happen automatically.</value>
<value>ar ôl 2 funud</value> <value>ar ôl 2 funud</value>
</data> </data>
<data name="ClearClipboard" xml:space="preserve"> <data name="ClearClipboard" xml:space="preserve">
<value>Clear clipboard</value> <value>Clirio'r clipfwrdd</value>
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment> <comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
</data> </data>
<data name="ClearClipboardDescription" xml:space="preserve"> <data name="ClearClipboardDescription" xml:space="preserve">
<value>Automatically clear copied values from your clipboard.</value> <value>Clirio eitemau a gopïwyd o'ch clipfwrdd yn awtomatig.</value>
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment> <comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
</data> </data>
<data name="DefaultUriMatchDetection" xml:space="preserve"> <data name="DefaultUriMatchDetection" xml:space="preserve">
@@ -1541,7 +1541,7 @@ Scanning will happen automatically.</value>
<comment>Color theme</comment> <comment>Color theme</comment>
</data> </data>
<data name="ThemeDescription" xml:space="preserve"> <data name="ThemeDescription" xml:space="preserve">
<value>Change the application's color theme.</value> <value>Newid thema liwiau'r ap.</value>
</data> </data>
<data name="ThemeDefault" xml:space="preserve"> <data name="ThemeDefault" xml:space="preserve">
<value>Rhagosodiad (system)</value> <value>Rhagosodiad (system)</value>
@@ -1550,13 +1550,13 @@ Scanning will happen automatically.</value>
<value>Default dark theme</value> <value>Default dark theme</value>
</data> </data>
<data name="CopyNotes" xml:space="preserve"> <data name="CopyNotes" xml:space="preserve">
<value>Copy note</value> <value>Copïo'r nodyn</value>
</data> </data>
<data name="Exit" xml:space="preserve"> <data name="Exit" xml:space="preserve">
<value>Exit</value> <value>Gadael</value>
</data> </data>
<data name="ExitConfirmation" xml:space="preserve"> <data name="ExitConfirmation" xml:space="preserve">
<value>Are you sure you want to exit Bitwarden?</value> <value>Ydych chi'n siŵr eich bod am adael Bitwarden?</value>
</data> </data>
<data name="PINRequireMasterPasswordRestart" xml:space="preserve"> <data name="PINRequireMasterPasswordRestart" xml:space="preserve">
<value>Do you want to require unlocking with your master password when the application is restarted?</value> <value>Do you want to require unlocking with your master password when the application is restarted?</value>
@@ -1599,7 +1599,7 @@ Scanning will happen automatically.</value>
<value>Cynnwys rhif</value> <value>Cynnwys rhif</value>
</data> </data>
<data name="Download" xml:space="preserve"> <data name="Download" xml:space="preserve">
<value>Download</value> <value>Lawrlwytho</value>
</data> </data>
<data name="Shared" xml:space="preserve"> <data name="Shared" xml:space="preserve">
<value>Shared</value> <value>Shared</value>
@@ -1614,10 +1614,10 @@ Scanning will happen automatically.</value>
<value>Biometric verification</value> <value>Biometric verification</value>
</data> </data>
<data name="Biometrics" xml:space="preserve"> <data name="Biometrics" xml:space="preserve">
<value>Biometrics</value> <value>biometreg</value>
</data> </data>
<data name="UseBiometricsToUnlock" xml:space="preserve"> <data name="UseBiometricsToUnlock" xml:space="preserve">
<value>Use biometrics to unlock</value> <value>Defnyddio biometreg i ddatgloi</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>
@@ -1641,7 +1641,7 @@ Scanning will happen automatically.</value>
<value>Granted</value> <value>Granted</value>
</data> </data>
<data name="FileFormat" xml:space="preserve"> <data name="FileFormat" xml:space="preserve">
<value>File format</value> <value>Fformat y ffeil</value>
</data> </data>
<data name="ExportVaultMasterPasswordDescription" xml:space="preserve"> <data name="ExportVaultMasterPasswordDescription" xml:space="preserve">
<value>Rhowch eich prif gyfrinair i allforio data eich cell.</value> <value>Rhowch eich prif gyfrinair i allforio data eich cell.</value>
@@ -1692,7 +1692,7 @@ Scanning will happen automatically.</value>
<value>There was a problem saving this attachment. If the problem persists, you can save it from the web vault.</value> <value>There was a problem saving this attachment. If the problem persists, you can save it from the web vault.</value>
</data> </data>
<data name="SaveAttachmentSuccess" xml:space="preserve"> <data name="SaveAttachmentSuccess" xml:space="preserve">
<value>Attachment saved successfully</value> <value>Cadwyd yr atodiad yn llwyddiannus</value>
</data> </data>
<data name="AutofillTileAccessibilityRequired" xml:space="preserve"> <data name="AutofillTileAccessibilityRequired" xml:space="preserve">
<value>Please turn on "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>
@@ -1701,11 +1701,11 @@ Scanning will happen automatically.</value>
<value>No password fields detected</value> <value>No password fields detected</value>
</data> </data>
<data name="SoftDeleting" xml:space="preserve"> <data name="SoftDeleting" xml:space="preserve">
<value>Sending to trash...</value> <value>Yn anfon i'r bin sbwriel...</value>
<comment>Message shown when interacting with the server</comment> <comment>Message shown when interacting with the server</comment>
</data> </data>
<data name="ItemSoftDeleted" xml:space="preserve"> <data name="ItemSoftDeleted" xml:space="preserve">
<value>Item has been sent to trash.</value> <value>Anfonwyd yr eitem i'r bin sbwriel.</value>
<comment>Confirmation message after successfully soft-deleting a login</comment> <comment>Confirmation message after successfully soft-deleting a login</comment>
</data> </data>
<data name="Restore" xml:space="preserve"> <data name="Restore" xml:space="preserve">
@@ -1713,7 +1713,7 @@ Scanning will happen automatically.</value>
<comment>Restores an entity (verb).</comment> <comment>Restores an entity (verb).</comment>
</data> </data>
<data name="Restoring" xml:space="preserve"> <data name="Restoring" xml:space="preserve">
<value>Restoring...</value> <value>Yn adfer...</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">
@@ -1721,15 +1721,15 @@ Scanning will happen automatically.</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">
<value>Trash</value> <value>Bin sbwriel</value>
<comment>(noun) Location of deleted items which have not yet been permanently deleted</comment> <comment>(noun) Location of deleted items which have not yet been permanently deleted</comment>
</data> </data>
<data name="SearchTrash" xml:space="preserve"> <data name="SearchTrash" xml:space="preserve">
<value>Search trash</value> <value>Chwilio drwy'r bin sbwriel</value>
<comment>(action prompt) Label for the search text field when viewing the trash folder</comment> <comment>(action prompt) Label for the search text field when viewing the trash folder</comment>
</data> </data>
<data name="DoYouReallyWantToPermanentlyDeleteCipher" xml:space="preserve"> <data name="DoYouReallyWantToPermanentlyDeleteCipher" xml:space="preserve">
<value>Do you really want to permanently delete? This cannot be undone.</value> <value>Ydych chi wir eisiau dileu'r eitem hon? Allwch chi ddim dadwneud hyn.</value>
<comment>Confirmation alert message when permanently deleteing a cipher.</comment> <comment>Confirmation alert message when permanently deleteing a cipher.</comment>
</data> </data>
<data name="DoYouReallyWantToRestoreCipher" xml:space="preserve"> <data name="DoYouReallyWantToRestoreCipher" xml:space="preserve">
@@ -1737,7 +1737,7 @@ Scanning will happen automatically.</value>
<comment>Confirmation alert message when restoring a soft-deleted cipher.</comment> <comment>Confirmation alert message when restoring a soft-deleted cipher.</comment>
</data> </data>
<data name="DoYouReallyWantToSoftDeleteCipher" xml:space="preserve"> <data name="DoYouReallyWantToSoftDeleteCipher" xml:space="preserve">
<value>Do you really want to send to the trash?</value> <value>Ydych chi wir eisiau anfon yr eitem hon i'r bin sbwriel?</value>
<comment>Confirmation alert message when soft-deleting a cipher.</comment> <comment>Confirmation alert message when soft-deleting a cipher.</comment>
</data> </data>
<data name="AccountBiometricInvalidated" xml:space="preserve"> <data name="AccountBiometricInvalidated" xml:space="preserve">
@@ -1747,10 +1747,10 @@ Scanning will happen automatically.</value>
<value>Autofill biometric unlock for this account is disabled pending verification of master password.</value> <value>Autofill biometric unlock for this account is disabled pending verification of master password.</value>
</data> </data>
<data name="EnableSyncOnRefresh" xml:space="preserve"> <data name="EnableSyncOnRefresh" xml:space="preserve">
<value>Allow sync on refresh</value> <value>Caniatáu cysoni wrth adnewyddu</value>
</data> </data>
<data name="EnableSyncOnRefreshDescription" xml:space="preserve"> <data name="EnableSyncOnRefreshDescription" xml:space="preserve">
<value>Syncing vault with pull down gesture.</value> <value>Cysoni'r gell drwy dynnu i lawr.</value>
</data> </data>
<data name="LogInSso" xml:space="preserve"> <data name="LogInSso" xml:space="preserve">
<value>Enterprise single sign-on</value> <value>Enterprise single sign-on</value>
@@ -1765,7 +1765,7 @@ Scanning will happen automatically.</value>
<value>Currently unable to login with SSO</value> <value>Currently unable to login with SSO</value>
</data> </data>
<data name="SetMasterPassword" xml:space="preserve"> <data name="SetMasterPassword" xml:space="preserve">
<value>Set master password</value> <value>Gosod prif gyfrinair</value>
</data> </data>
<data name="SetMasterPasswordSummary" xml:space="preserve"> <data name="SetMasterPasswordSummary" xml:space="preserve">
<value>In order to complete logging in with SSO, please set a master password to access and protect your vault.</value> <value>In order to complete logging in with SSO, please set a master password to access and protect your vault.</value>
@@ -1798,7 +1798,7 @@ Scanning will happen automatically.</value>
<value>Password does not meet organization requirements. Please check the policy information and try again.</value> <value>Password does not meet organization requirements. Please check the policy information and try again.</value>
</data> </data>
<data name="Loading" xml:space="preserve"> <data name="Loading" xml:space="preserve">
<value>Loading</value> <value>Llwytho</value>
</data> </data>
<data name="AcceptPolicies" xml:space="preserve"> <data name="AcceptPolicies" xml:space="preserve">
<value>By activating this switch you agree to the following: <value>By activating this switch you agree to the following:
@@ -1808,16 +1808,16 @@ Scanning will happen automatically.</value>
<value>Terms of Service and Privacy Policy have not been acknowledged.</value> <value>Terms of Service and Privacy Policy have not been acknowledged.</value>
</data> </data>
<data name="TermsOfService" xml:space="preserve"> <data name="TermsOfService" xml:space="preserve">
<value>Terms of Service</value> <value>Telerau gwasanaeth</value>
</data> </data>
<data name="PrivacyPolicy" xml:space="preserve"> <data name="PrivacyPolicy" xml:space="preserve">
<value>Privacy Policy</value> <value>Polisi preifatrwydd</value>
</data> </data>
<data name="AccessibilityDrawOverPermissionAlert" xml:space="preserve"> <data name="AccessibilityDrawOverPermissionAlert" xml:space="preserve">
<value>Bitwarden needs attention - Turn on "Draw-Over" in "Auto-fill Services" from Bitwarden Settings</value> <value>Bitwarden needs attention - Turn on "Draw-Over" in "Auto-fill Services" from Bitwarden Settings</value>
</data> </data>
<data name="AutofillServices" xml:space="preserve"> <data name="AutofillServices" xml:space="preserve">
<value>Auto-fill services</value> <value>Gwasanaethau llenwi awtomatig</value>
</data> </data>
<data name="InlineAutofill" xml:space="preserve"> <data name="InlineAutofill" xml:space="preserve">
<value>Use inline autofill</value> <value>Use inline autofill</value>
@@ -2044,11 +2044,11 @@ 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="AboutSend" xml:space="preserve"> <data name="AboutSend" xml:space="preserve">
<value>About Send</value> <value>Ynghylch 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="HideEmail" xml:space="preserve"> <data name="HideEmail" xml:space="preserve">
<value>Hide my email address from recipients</value> <value>Cuddio fy nghyfeiriad ebost rhag derbynwyr</value>
</data> </data>
<data name="SendOptionsPolicyInEffect" xml:space="preserve"> <data name="SendOptionsPolicyInEffect" xml:space="preserve">
<value>One or more organization policies are affecting your Send options.</value> <value>One or more organization policies are affecting your Send options.</value>
@@ -2063,7 +2063,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="PasswordPrompt" xml:space="preserve"> <data name="PasswordPrompt" xml:space="preserve">
<value>Master password re-prompt</value> <value>Ailofyn am y prif gyfrinair</value>
</data> </data>
<data name="PasswordConfirmation" xml:space="preserve"> <data name="PasswordConfirmation" xml:space="preserve">
<value>Master password confirmation</value> <value>Master password confirmation</value>
@@ -2078,16 +2078,16 @@ Scanning will happen automatically.</value>
<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>Diweddarwyd y prif gyfrinair</value>
</data> </data>
<data name="UpdateMasterPassword" xml:space="preserve"> <data name="UpdateMasterPassword" xml:space="preserve">
<value>Update master password</value> <value>Diweddaru'r prif gyfrinair</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 organization. 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 organization. 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>Yn diweddaru'r cyfrinair</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>
@@ -2105,7 +2105,7 @@ Scanning will happen automatically.</value>
<value>Leave organization</value> <value>Leave organization</value>
</data> </data>
<data name="LeaveOrganizationName" xml:space="preserve"> <data name="LeaveOrganizationName" xml:space="preserve">
<value>Leave {0}?</value> <value>Gadael {0}?</value>
</data> </data>
<data name="Fido2Title" xml:space="preserve"> <data name="Fido2Title" xml:space="preserve">
<value>FIDO2 WebAuthn</value> <value>FIDO2 WebAuthn</value>
@@ -2120,7 +2120,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>Dychwelyd i'r ap</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>
@@ -2144,7 +2144,7 @@ Scanning will happen automatically.</value>
<value>One or more organization policies prevents your from exporting your individual vault.</value> <value>One or more organization 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>Ychwanegu cyfrif</value>
</data> </data>
<data name="AccountUnlocked" xml:space="preserve"> <data name="AccountUnlocked" xml:space="preserve">
<value>Unlocked</value> <value>Unlocked</value>
@@ -2168,19 +2168,19 @@ Scanning will happen automatically.</value>
<value>Account removed successfully</value> <value>Account removed successfully</value>
</data> </data>
<data name="DeleteAccount" xml:space="preserve"> <data name="DeleteAccount" xml:space="preserve">
<value>Delete account</value> <value>Dileu eich cyfrif</value>
</data> </data>
<data name="DeletingYourAccountIsPermanent" xml:space="preserve"> <data name="DeletingYourAccountIsPermanent" xml:space="preserve">
<value>Deleting your account is permanent</value> <value>Deleting your account is permanent</value>
</data> </data>
<data name="DeleteAccountExplanation" xml:space="preserve"> <data name="DeleteAccountExplanation" xml:space="preserve">
<value>Your account and all vault data will be erased and unrecoverable. Are you sure you want to continue?</value> <value>Caiff eich cyfrif a holl ddata'ch cell eu dileu mewn ffordd anadferadwy. Ydych chi'n siŵr yr hoffech chi barhau?</value>
</data> </data>
<data name="DeletingYourAccount" xml:space="preserve"> <data name="DeletingYourAccount" xml:space="preserve">
<value>Deleting your account</value> <value>Deleting your account</value>
</data> </data>
<data name="YourAccountHasBeenPermanentlyDeleted" xml:space="preserve"> <data name="YourAccountHasBeenPermanentlyDeleted" xml:space="preserve">
<value>Your account has been permanently deleted</value> <value>Mae eich cyfrif wedi cael ei ddileu'n barhaol</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>
@@ -2249,7 +2249,7 @@ Scanning will happen automatically.</value>
<value>Password is not visible, tap to show.</value> <value>Password is not visible, tap to show.</value>
</data> </data>
<data name="FilterByVault" xml:space="preserve"> <data name="FilterByVault" xml:space="preserve">
<value>Filter items by vault</value> <value>Hidlo eitemau yn ôl cell</value>
</data> </data>
<data name="AllVaults" xml:space="preserve"> <data name="AllVaults" xml:space="preserve">
<value>Pob cell</value> <value>Pob cell</value>
@@ -2307,7 +2307,7 @@ select Add TOTP to store the key safely</value>
<value>We were unable to process your request. Please try again or contact us.</value> <value>We were unable to process your request. Please try again or contact us.</value>
</data> </data>
<data name="AllowScreenCapture" xml:space="preserve"> <data name="AllowScreenCapture" xml:space="preserve">
<value>Allow screen capture</value> <value>Caniatáu sgrinluniau</value>
</data> </data>
<data name="AreYouSureYouWantToEnableScreenCapture" xml:space="preserve"> <data name="AreYouSureYouWantToEnableScreenCapture" xml:space="preserve">
<value>Are you sure you want to turn on screen capture?</value> <value>Are you sure you want to turn on screen capture?</value>
@@ -2316,46 +2316,46 @@ select Add TOTP to store the key safely</value>
<value>Login requested</value> <value>Login requested</value>
</data> </data>
<data name="AreYouTryingToLogIn" xml:space="preserve"> <data name="AreYouTryingToLogIn" xml:space="preserve">
<value>Are you trying to log in?</value> <value>Ydych chi'n ceisio mewngofnodi?</value>
</data> </data>
<data name="LogInAttemptByXOnY" xml:space="preserve"> <data name="LogInAttemptByXOnY" xml:space="preserve">
<value>Login attempt by {0} on {1}</value> <value>Cais mewngofnodi gan {0} ar {1}</value>
</data> </data>
<data name="DeviceType" xml:space="preserve"> <data name="DeviceType" xml:space="preserve">
<value>Device type</value> <value>Math o ddyfais</value>
</data> </data>
<data name="IpAddress" xml:space="preserve"> <data name="IpAddress" xml:space="preserve">
<value>Cyfeiriad IP</value> <value>Cyfeiriad IP</value>
</data> </data>
<data name="Time" xml:space="preserve"> <data name="Time" xml:space="preserve">
<value>Time</value> <value>Amser</value>
</data> </data>
<data name="Near" xml:space="preserve"> <data name="Near" xml:space="preserve">
<value>Near</value> <value>Gerllaw</value>
</data> </data>
<data name="ConfirmLogIn" xml:space="preserve"> <data name="ConfirmLogIn" xml:space="preserve">
<value>Confirm login</value> <value>Cadarnhau'r mewngofnodi</value>
</data> </data>
<data name="DenyLogIn" xml:space="preserve"> <data name="DenyLogIn" xml:space="preserve">
<value>Deny login</value> <value>Gwrthod y mewngofnodi</value>
</data> </data>
<data name="JustNow" xml:space="preserve"> <data name="JustNow" xml:space="preserve">
<value>Just now</value> <value>Ychydig yn ôl</value>
</data> </data>
<data name="XMinutesAgo" xml:space="preserve"> <data name="XMinutesAgo" xml:space="preserve">
<value>{0} minutes ago</value> <value>{0} o funudau yn ôl</value>
</data> </data>
<data name="LogInAccepted" xml:space="preserve"> <data name="LogInAccepted" xml:space="preserve">
<value>Login confirmed</value> <value>Cadarnhawyd y mewngofnodi</value>
</data> </data>
<data name="LogInDenied" xml:space="preserve"> <data name="LogInDenied" xml:space="preserve">
<value>Login denied</value> <value>Gwrthodwyd y mewngofnodi</value>
</data> </data>
<data name="ApproveLoginRequests" xml:space="preserve"> <data name="ApproveLoginRequests" xml:space="preserve">
<value>Approve login requests</value> <value>Cymeradwyo ceisiadau mewngofnodi</value>
</data> </data>
<data name="UseThisDeviceToApproveLoginRequestsMadeFromOtherDevices" xml:space="preserve"> <data name="UseThisDeviceToApproveLoginRequestsMadeFromOtherDevices" xml:space="preserve">
<value>Use this device to approve login requests made from other devices</value> <value>Defnyddio'r ddyfais hon i gymeradwyo ceisiadau mewngofnodi gan ddyfeisiau eraill</value>
</data> </data>
<data name="AllowNotifications" xml:space="preserve"> <data name="AllowNotifications" xml:space="preserve">
<value>Caniatáu hysbysiadau</value> <value>Caniatáu hysbysiadau</value>
@@ -2373,16 +2373,16 @@ 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>Math o gyfrinair</value>
</data> </data>
<data name="WhatWouldYouLikeToGenerate" xml:space="preserve"> <data name="WhatWouldYouLikeToGenerate" xml:space="preserve">
<value>What would you like to generate?</value> <value>Beth hoffech chi ei gynhyrchu?</value>
</data> </data>
<data name="UsernameType" xml:space="preserve"> <data name="UsernameType" xml:space="preserve">
<value>Math o enw defnyddiwr</value> <value>Math o enw defnyddiwr</value>
</data> </data>
<data name="PlusAddressedEmail" xml:space="preserve"> <data name="PlusAddressedEmail" xml:space="preserve">
<value>Plus addressed email</value> <value>Is-gyfeiriad ebost</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>
@@ -2391,13 +2391,13 @@ select Add TOTP to store the key safely</value>
<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>Gair ar hap</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>Enw parth (gofynnol)</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>
@@ -2442,13 +2442,13 @@ select Add TOTP to store the key safely</value>
<value>Math o ebost</value> <value>Math o ebost</value>
</data> </data>
<data name="WebsiteRequired" xml:space="preserve"> <data name="WebsiteRequired" xml:space="preserve">
<value>Website (required)</value> <value>Gwefan (gofynnol)</value>
</data> </data>
<data name="UnknownXErrorMessage" xml:space="preserve"> <data name="UnknownXErrorMessage" xml:space="preserve">
<value>Unknown {0} error occurred.</value> <value>Bu gwall anhysbys {0}.</value>
</data> </data>
<data name="PlusAddressedEmailDescription" xml:space="preserve"> <data name="PlusAddressedEmailDescription" xml:space="preserve">
<value>Use your email provider's subaddress capabilities</value> <value>Defnyddio galluoedd is-gyfeirio darparwr eich cyfeiriad ebost ('plus addressing')</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>Use your domain's configured catch-all inbox.</value>
@@ -2457,7 +2457,7 @@ select Add TOTP to store the key safely</value>
<value>Generate an email alias with an external forwarding service.</value> <value>Generate an email alias with an external forwarding service.</value>
</data> </data>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Random</value> <value>Hap</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve"> <data name="ConnectToWatch" xml:space="preserve">
<value>Connect to Watch</value> <value>Connect to Watch</value>
@@ -2469,10 +2469,10 @@ select Add TOTP to store the key safely</value>
<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 &amp; 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 uses the Accessibility Service to search for login fields in apps and websites, then establish the appropriate field IDs for entering a username &amp; 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>
</data> </data>
<data name="Accept" xml:space="preserve"> <data name="Accept" xml:space="preserve">
<value>Accept</value> <value>Derbyn</value>
</data> </data>
<data name="Decline" xml:space="preserve"> <data name="Decline" xml:space="preserve">
<value>Decline</value> <value>Gwrthod</value>
</data> </data>
<data name="LoginRequestHasAlreadyExpired" xml:space="preserve"> <data name="LoginRequestHasAlreadyExpired" xml:space="preserve">
<value>Login request has already expired.</value> <value>Login request has already expired.</value>
@@ -2483,22 +2483,22 @@ 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>New around here?</value> <value>Ydych chi'n newydd?</value>
</data> </data>
<data name="GetMasterPasswordwordHint" xml:space="preserve"> <data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Get master password hint</value> <value>Anfon awgrym o'ch prif gyfrinair</value>
</data> </data>
<data name="LoggingInAsXOnY" xml:space="preserve"> <data name="LoggingInAsXOnY" xml:space="preserve">
<value>Logging in as {0} on {1}</value> <value>Yn mewngofnodi fel {0} ar {1}</value>
</data> </data>
<data name="NotYou" xml:space="preserve"> <data name="NotYou" xml:space="preserve">
<value>Not you?</value> <value>Nid chi?</value>
</data> </data>
<data name="LogInWithMasterPassword" xml:space="preserve"> <data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log in with master password</value> <value>Mewngofnodi â'ch prif gyfrinair</value>
</data> </data>
<data name="LogInWithAnotherDevice" xml:space="preserve"> <data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log in with device</value> <value>Mewngofnodi â dyfais</value>
</data> </data>
<data name="LogInInitiated" xml:space="preserve"> <data name="LogInInitiated" xml:space="preserve">
<value>Login initiated</value> <value>Login initiated</value>
@@ -2513,13 +2513,13 @@ Do you want to switch to this account?</value>
<value>Resend notification</value> <value>Resend notification</value>
</data> </data>
<data name="NeedAnotherOption" xml:space="preserve"> <data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value> <value>Angen opsiwn arall?</value>
</data> </data>
<data name="ViewAllLoginOptions" xml:space="preserve"> <data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value> <value>View all log in options</value>
</data> </data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve"> <data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value> <value>Dyw'r cais hwn ddim yn ddilys bellach</value>
</data> </data>
<data name="PendingLogInRequests" xml:space="preserve"> <data name="PendingLogInRequests" xml:space="preserve">
<value>Pending login requests</value> <value>Pending login requests</value>
@@ -2540,13 +2540,13 @@ Do you want to switch to this account?</value>
<value>Enable camera permission to use the scanner</value> <value>Enable camera permission to use the scanner</value>
</data> </data>
<data name="Language" xml:space="preserve"> <data name="Language" xml:space="preserve">
<value>Language</value> <value>Iaith</value>
</data> </data>
<data name="LanguageChangeXDescription" xml:space="preserve"> <data name="LanguageChangeXDescription" xml:space="preserve">
<value>The language has been changed to {0}. Please restart the app to see the change</value> <value>Cafodd yr iaith ei newid i {0}. Ailgychwynnwch yr ap i weld newidiadau</value>
</data> </data>
<data name="LanguageChangeRequiresAppRestart" xml:space="preserve"> <data name="LanguageChangeRequiresAppRestart" xml:space="preserve">
<value>Language change requires app restart</value> <value>Bydd angen ailgychwyn yr ap</value>
</data> </data>
<data name="DefaultSystem" xml:space="preserve"> <data name="DefaultSystem" xml:space="preserve">
<value>Default (System)</value> <value>Default (System)</value>
@@ -2573,7 +2573,7 @@ Do you want to switch to this account?</value>
<value>Cryf</value> <value>Cryf</value>
</data> </data>
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve"> <data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
<value>Check known data breaches for this password</value> <value>Chwilio am achosion o ddatgelu data sy'n cynnwys y cyfrinair hwn</value>
</data> </data>
<data name="ExposedMasterPassword" xml:space="preserve"> <data name="ExposedMasterPassword" xml:space="preserve">
<value>Prif gyfrinair wedi'i ddatgelu</value> <value>Prif gyfrinair wedi'i ddatgelu</value>
@@ -2609,7 +2609,7 @@ Do you want to switch to this account?</value>
<value>UE</value> <value>UE</value>
</data> </data>
<data name="SelfHosted" xml:space="preserve"> <data name="SelfHosted" xml:space="preserve">
<value>Hunangynhaliol</value> <value>Gweinydd hunangynhaliol</value>
</data> </data>
<data name="DataRegion" xml:space="preserve"> <data name="DataRegion" xml:space="preserve">
<value>Lleoliad y data</value> <value>Lleoliad y data</value>
@@ -2639,7 +2639,7 @@ Do you want to switch to this account?</value>
<value>Turn off using a public device</value> <value>Turn off using a public device</value>
</data> </data>
<data name="RememberThisDevice" xml:space="preserve"> <data name="RememberThisDevice" xml:space="preserve">
<value>Remember this device</value> <value>Cofio'r ddyfais hon</value>
</data> </data>
<data name="Passkey" xml:space="preserve"> <data name="Passkey" xml:space="preserve">
<value>Passkey</value> <value>Passkey</value>
@@ -2690,7 +2690,7 @@ Do you want to switch to this account?</value>
<value>Trouble logging in?</value> <value>Trouble logging in?</value>
</data> </data>
<data name="LoggingInAsX" xml:space="preserve"> <data name="LoggingInAsX" xml:space="preserve">
<value>Logging in as {0}</value> <value>Yn mewngofnodi fel {0}</value>
</data> </data>
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve"> <data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
<value>Vault timeout action changed to log out</value> <value>Vault timeout action changed to log out</value>
@@ -2745,19 +2745,19 @@ Do you want to switch to this account?</value>
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value> <value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
</data> </data>
<data name="LogInWithDevice" xml:space="preserve"> <data name="LogInWithDevice" xml:space="preserve">
<value>Log in with device</value> <value>Mewngofnodi â dyfais</value>
</data> </data>
<data name="LoggingInOn" xml:space="preserve"> <data name="LoggingInOn" xml:space="preserve">
<value>Logging in on</value> <value>Mewngofnodi ar</value>
</data> </data>
<data name="Vault" xml:space="preserve"> <data name="Vault" xml:space="preserve">
<value>Vault</value> <value>Cell</value>
</data> </data>
<data name="Appearance" xml:space="preserve"> <data name="Appearance" xml:space="preserve">
<value>Appearance</value> <value>Golwg</value>
</data> </data>
<data name="AccountSecurity" xml:space="preserve"> <data name="AccountSecurity" xml:space="preserve">
<value>Account security</value> <value>Diogelwch eich cyfrif</value>
</data> </data>
<data name="BitwardenHelpCenter" xml:space="preserve"> <data name="BitwardenHelpCenter" xml:space="preserve">
<value>Bitwarden Help Center</value> <value>Bitwarden Help Center</value>
@@ -2769,10 +2769,10 @@ Do you want to switch to this account?</value>
<value>Copy app information</value> <value>Copy app information</value>
</data> </data>
<data name="SyncNow" xml:space="preserve"> <data name="SyncNow" xml:space="preserve">
<value>Sync now</value> <value>Cysoni nawr</value>
</data> </data>
<data name="UnlockOptions" xml:space="preserve"> <data name="UnlockOptions" xml:space="preserve">
<value>Unlock options</value> <value>Dewisiadau datgloi</value>
</data> </data>
<data name="SessionTimeout" xml:space="preserve"> <data name="SessionTimeout" xml:space="preserve">
<value>Session timeout</value> <value>Session timeout</value>
@@ -2806,10 +2806,10 @@ Do you want to switch to this account?</value>
<value>Use inline autofill if your selected keyboard supports it. Otherwise, use the default overlay.</value> <value>Use inline autofill if your selected keyboard supports it. Otherwise, use the default overlay.</value>
</data> </data>
<data name="AdditionalOptions" xml:space="preserve"> <data name="AdditionalOptions" xml:space="preserve">
<value>Additional options</value> <value>Dewisiadau ychwanegol</value>
</data> </data>
<data name="ContinueToWebApp" xml:space="preserve"> <data name="ContinueToWebApp" xml:space="preserve">
<value>Continue to web app?</value> <value>Parhau i'r ap gwe?</value>
</data> </data>
<data name="ContinueToX" xml:space="preserve"> <data name="ContinueToX" xml:space="preserve">
<value>Continue to {0}?</value> <value>Continue to {0}?</value>
@@ -2821,11 +2821,14 @@ Do you want to switch to this account?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
<data name="TwoStepLoginDescriptionLong" xml:space="preserve"> <data name="TwoStepLoginDescriptionLong" xml:space="preserve">
<value>Make your account more secure by setting up two-step login in the Bitwarden web app.</value> <value>Gallwch wneud eich cyfrif yn fwy diogel drwy alluogi mewngofnodi dau gam yn ap gwe Bitwarden.</value>
</data> </data>
<data name="ChangeMasterPasswordDescriptionLong" xml:space="preserve"> <data name="ChangeMasterPasswordDescriptionLong" xml:space="preserve">
<value>You can change your master password on the Bitwarden web app.</value> <value>You can change your master password on the Bitwarden web app.</value>
@@ -2840,6 +2843,9 @@ Do you want to switch to this account?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2820,6 +2820,9 @@ Vil du skifte til denne konto?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Fortsæt med at kontakte support?</value> <value>Fortsæt med at kontakte support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Fortsæt til Fortrolighedspolitik?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Fortsæt til app-butik?</value> <value>Fortsæt til app-butik?</value>
</data> </data>
@@ -2839,6 +2842,9 @@ Vil du skifte til denne konto?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Kan ikke finde det, der søges efter? Kontakt Bitwarden-supporten via bitwarden.com.</value> <value>Kan ikke finde det, der søges efter? Kontakt Bitwarden-supporten via bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Tjek vores Fortrolighedspolitik på bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Tjek flere funktioner ud i Bitwarden-kontoen på web-appen.</value> <value>Tjek flere funktioner ud i Bitwarden-kontoen på web-appen.</value>
</data> </data>

View File

@@ -2819,6 +2819,9 @@ Möchtest du zu diesem Konto wechseln?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Weiter, um den Support zu kontaktieren?</value> <value>Weiter, um den Support zu kontaktieren?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Weiter zur Datenschutzerklärung?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Weiter zum App Store?</value> <value>Weiter zum App Store?</value>
</data> </data>
@@ -2838,6 +2841,9 @@ Möchtest du zu diesem Konto wechseln?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Du findest nicht, was du suchst? Kontaktiere den Bitwarden Support auf bitwarden.com.</value> <value>Du findest nicht, was du suchst? Kontaktiere den Bitwarden Support auf bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Lies unsere Datenschutzerklärung auf bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Entdecke mehr Funktionen deines Bitwarden-Kontos in der Web-App.</value> <value>Entdecke mehr Funktionen deines Bitwarden-Kontos in der Web-App.</value>
</data> </data>

View File

@@ -2819,6 +2819,9 @@
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Συνέχεια στην επικοινωνία με την υποστήριξη;</value> <value>Συνέχεια στην επικοινωνία με την υποστήριξη;</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Συνέχεια στο κατάστημα εφαρμογών;</value> <value>Συνέχεια στο κατάστημα εφαρμογών;</value>
</data> </data>
@@ -2838,6 +2841,9 @@
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Δεν μπορείτε να βρείτε αυτό που ψάχνετε; Επικοινωνήστε με την υποστήριξη Bitwarden στο bitwarden.com.</value> <value>Δεν μπορείτε να βρείτε αυτό που ψάχνετε; Επικοινωνήστε με την υποστήριξη Bitwarden στο bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Εξερευνήστε περισσότερες δυνατότητες του Bitwarden λογαριασμού σας, στην εφαρμογή διαδικτύου.</value> <value>Εξερευνήστε περισσότερες δυνατότητες του Bitwarden λογαριασμού σας, στην εφαρμογή διαδικτύου.</value>
</data> </data>

View File

@@ -2820,6 +2820,9 @@ Do you want to switch to this account?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2839,6 +2842,9 @@ Do you want to switch to this account?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2834,6 +2834,9 @@ Do you want to switch to this account?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2853,6 +2856,9 @@ Do you want to switch to this account?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2822,6 +2822,9 @@ seleccione Agregar TOTP para almacenar la clave de forma segura</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>¿Continuar con el servicio de asistencia?</value> <value>¿Continuar con el servicio de asistencia?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>¿Continuar a la App Store?</value> <value>¿Continuar a la App Store?</value>
</data> </data>
@@ -2841,6 +2844,9 @@ seleccione Agregar TOTP para almacenar la clave de forma segura</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>¿No encuentras lo que estás buscando? Contacta con el soporte de Bitwarden en bitwarden.com.</value> <value>¿No encuentras lo que estás buscando? Contacta con el soporte de Bitwarden en bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explora más características de tu cuenta de Bitwarden en la aplicación web.</value> <value>Explora más características de tu cuenta de Bitwarden en la aplicación web.</value>
</data> </data>

View File

@@ -2820,6 +2820,9 @@ Soovid selle konto peale lülituda?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2839,6 +2842,9 @@ Soovid selle konto peale lülituda?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2819,6 +2819,9 @@ Kontu honetara aldatu nahi duzu?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2838,6 +2841,9 @@ Kontu honetara aldatu nahi duzu?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2821,6 +2821,9 @@
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>می‌خواهید با پشتیبانی تماس بگیرید؟</value> <value>می‌خواهید با پشتیبانی تماس بگیرید؟</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>به فروشگاه برنامه ادامه می‌دهید؟</value> <value>به فروشگاه برنامه ادامه می‌دهید؟</value>
</data> </data>
@@ -2840,6 +2843,9 @@
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>چیزی را که به دنبالش هستید پیدا نمی‌کنید؟ با پشتیبانی Bitwarden در bitwarden.com تماس بگیرید.</value> <value>چیزی را که به دنبالش هستید پیدا نمی‌کنید؟ با پشتیبانی Bitwarden در bitwarden.com تماس بگیرید.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>ویژگی‌های بیشتر حساب Bitwarden خود را در برنامه وب کاوش کنید.</value> <value>ویژگی‌های بیشتر حساب Bitwarden خود را در برنامه وب کاوش کنید.</value>
</data> </data>

View File

@@ -560,7 +560,7 @@
<comment>Message shown when interacting with the server</comment> <comment>Message shown when interacting with the server</comment>
</data> </data>
<data name="LoginOrCreateNewAccount" xml:space="preserve"> <data name="LoginOrCreateNewAccount" xml:space="preserve">
<value>Kirjaudu tai luo uusi tili käyttääksesi salattua holviasi.</value> <value>Käytä salattua holviasi kirjautumalla sisään tai tai luo uusi tili.</value>
</data> </data>
<data name="Manage" xml:space="preserve"> <data name="Manage" xml:space="preserve">
<value>Hallinta</value> <value>Hallinta</value>
@@ -2821,6 +2821,9 @@ Haluatko vaihtaa tähän tiliin?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Siirrytäänkö asiakaspalveluun?</value> <value>Siirrytäänkö asiakaspalveluun?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Jatketaanko tietosuojakäytäntöön?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Avataanko sovelluskauppa?</value> <value>Avataanko sovelluskauppa?</value>
</data> </data>
@@ -2840,6 +2843,9 @@ Haluatko vaihtaa tähän tiliin?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Etkö löydä etsimääsi? Tavoitat Bitwardenin asiakaspalvelun osoitteesta bitwarden.com.</value> <value>Etkö löydä etsimääsi? Tavoitat Bitwardenin asiakaspalvelun osoitteesta bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Tutustu tietosuojakäytäntöömme osoitteessa bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Tutustu Bitwarden-tilisi muihin omimaisuuksiin verkkosovelluksessa.</value> <value>Tutustu Bitwarden-tilisi muihin omimaisuuksiin verkkosovelluksessa.</value>
</data> </data>

View File

@@ -2821,6 +2821,9 @@ Gusto mo bang pumunta sa account na ito?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2840,6 +2843,9 @@ Gusto mo bang pumunta sa account na ito?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2821,6 +2821,9 @@ Voulez-vous basculer vers ce compte ?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continuer vers le contact du support ?</value> <value>Continuer vers le contact du support ?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Poursuivre vers la politique de confidentialité ?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continuer vers la boutique des applications ?</value> <value>Continuer vers la boutique des applications ?</value>
</data> </data>
@@ -2840,6 +2843,9 @@ Voulez-vous basculer vers ce compte ?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Vous ne trouvez pas ce que vous cherchez ? Contactez le support de Bitwarden sur bitwarden.com.</value> <value>Vous ne trouvez pas ce que vous cherchez ? Contactez le support de Bitwarden sur bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Consultez notre politique de confidentialité sur bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explorez plus de fonctionnalités de votre compte Bitwarden sur l'application Web.</value> <value>Explorez plus de fonctionnalités de votre compte Bitwarden sur l'application Web.</value>
</data> </data>

View File

@@ -2821,6 +2821,9 @@ Do you want to switch to this account?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2840,6 +2843,9 @@ Do you want to switch to this account?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2823,6 +2823,9 @@ Do you want to switch to this account?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2842,6 +2845,9 @@ Do you want to switch to this account?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2820,6 +2820,9 @@ Do you want to switch to this account?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2839,6 +2842,9 @@ Do you want to switch to this account?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2818,6 +2818,9 @@
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Kontaktiraj podršku?</value> <value>Kontaktiraj podršku?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Nastavi u trgovinu aplikacijama?</value> <value>Nastavi u trgovinu aplikacijama?</value>
</data> </data>
@@ -2837,6 +2840,9 @@
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Ne možeš naći što te zanima? Kontaktiraj Bitwarden podršku na bitwarden.com.</value> <value>Ne možeš naći što te zanima? Kontaktiraj Bitwarden podršku na bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Pronađi viđe značajki svojeg Bitwarden računa u web aplikaciji.</value> <value>Pronađi viđe značajki svojeg Bitwarden računa u web aplikaciji.</value>
</data> </data>

View File

@@ -2819,6 +2819,9 @@ Szeretnénk átváltani erre a fiókra?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Tovább az ügyfélszolgálathoz?</value> <value>Tovább az ügyfélszolgálathoz?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Tovább az adatvédelmi szabályzathoz?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Tovább az alkalmazásboltba?</value> <value>Tovább az alkalmazásboltba?</value>
</data> </data>
@@ -2838,6 +2841,9 @@ Szeretnénk átváltani erre a fiókra?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Nem találjuk, amit keresünk? Lépjünk kapcsolatba a Bitwarden ügyfélszolgálatával a bitwarden.com oldalon.</value> <value>Nem találjuk, amit keresünk? Lépjünk kapcsolatba a Bitwarden ügyfélszolgálatával a bitwarden.com oldalon.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Az adatvédelmi szabályzat megtekintése a bitwarden.com webhelyen.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Fedezzük fel a Bitwarden-fiók további funkcióit a webalkalmazásban.</value> <value>Fedezzük fel a Bitwarden-fiók további funkcióit a webalkalmazásban.</value>
</data> </data>

View File

@@ -2820,6 +2820,9 @@ Do you want to switch to this account?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2839,6 +2842,9 @@ Do you want to switch to this account?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2820,6 +2820,9 @@ Vuoi passare a questo account?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continua per contattare l'assistenza?</value> <value>Continua per contattare l'assistenza?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continuare alla privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continuare sull'App Store?</value> <value>Continuare sull'App Store?</value>
</data> </data>
@@ -2839,6 +2842,9 @@ Vuoi passare a questo account?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Non riesci a trovare quello che stai cercando? Contatta il supporto Bitwarden su bitwarden.com.</value> <value>Non riesci a trovare quello che stai cercando? Contatta il supporto Bitwarden su bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Consulta la nostra privacy policy su bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Esplora altre funzionalità del tuo account Bitwarden sul sito web.</value> <value>Esplora altre funzionalità del tuo account Bitwarden sul sito web.</value>
</data> </data>

View File

@@ -2820,6 +2820,9 @@
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>サポートに連絡しますか?</value> <value>サポートに連絡しますか?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>プライバシーポリシーを確認しますか?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>アプリストアに進みますか?</value> <value>アプリストアに進みますか?</value>
</data> </data>
@@ -2839,6 +2842,9 @@
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>お探しのものが見つかりませんか? bitwarden.com で Bitwarden のサポートにご連絡ください。</value> <value>お探しのものが見つかりませんか? bitwarden.com で Bitwarden のサポートにご連絡ください。</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>bitwarden.com でプライバシーポリシーをご覧ください。</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Bitwarden アカウントの機能をウェブアプリでご確認ください。</value> <value>Bitwarden アカウントの機能をウェブアプリでご確認ください。</value>
</data> </data>

View File

@@ -2821,6 +2821,9 @@ Do you want to switch to this account?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2840,6 +2843,9 @@ Do you want to switch to this account?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2821,6 +2821,9 @@ Do you want to switch to this account?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2840,6 +2843,9 @@ Do you want to switch to this account?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2820,6 +2820,9 @@ Do you want to switch to this account?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2839,6 +2842,9 @@ Do you want to switch to this account?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2821,6 +2821,9 @@ Ar norite pereiti prie šios paskyros?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2840,6 +2843,9 @@ Ar norite pereiti prie šios paskyros?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2821,6 +2821,9 @@ Vai pārslēgties uz šo kontu?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Pāriet uz sazināšanos ar atbalstu?</value> <value>Pāriet uz sazināšanos ar atbalstu?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Pāriet uz privātuma nosacījumiem?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Pāriet uz lietotņu veikalu?</value> <value>Pāriet uz lietotņu veikalu?</value>
</data> </data>
@@ -2840,6 +2843,9 @@ Vai pārslēgties uz šo kontu?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Meklējamais nav atrodams? Ir iespēja sazināties ar Bitwarden atbalstu bitwarden.com.</value> <value>Meklējamais nav atrodams? Ir iespēja sazināties ar Bitwarden atbalstu bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Mūsu privātuma nosacījumi ir pārskatāmi bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Vairāk sava Bitwarden konta iespēju var izpētīt tīmekļa vietnē.</value> <value>Vairāk sava Bitwarden konta iespēju var izpētīt tīmekļa vietnē.</value>
</data> </data>

View File

@@ -2820,6 +2820,9 @@ Do you want to switch to this account?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2839,6 +2842,9 @@ Do you want to switch to this account?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

View File

@@ -2821,6 +2821,9 @@ Do you want to switch to this account?</value>
<data name="ContinueToContactSupport" xml:space="preserve"> <data name="ContinueToContactSupport" xml:space="preserve">
<value>Continue to contact support?</value> <value>Continue to contact support?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value>
</data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continue to app store?</value> <value>Continue to app store?</value>
</data> </data>
@@ -2840,6 +2843,9 @@ Do you want to switch to this account?</value>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value>
</data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore more features of your Bitwarden account on the web app.</value>
</data> </data>

Some files were not shown because too many files have changed in this diff Show More