1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-05 23:53:33 +00:00

Compare commits

...

32 Commits

Author SHA1 Message Date
github-actions[bot]
43b7782872 Bumped version to 2.18.0 (#1893)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
(cherry picked from commit cdc41d3bef)
2022-04-27 08:25:37 -07:00
Federico Maccaroni
8f66e2a315 PS-291 Fix password history to update the collection on the main thread to load correctly (#1890) 2022-04-26 09:08:58 -04:00
sneakernuts
8e333e6d14 Switched org
(cherry picked from commit 9fd8dab9d6)
2022-04-22 07:44:22 -06:00
mp-bw
ac7a680a1b update XF and revert old workarounds (#1885) 2022-04-21 21:31:02 -04:00
mp-bw
88f6b60b97 Crash fixes (#1869)
* Crash fixes

* added HasAutofillService to DeviceActionService
2022-04-01 12:07:14 -04:00
github-actions[bot]
1f58b0cabe Autosync the updated translations (#1868)
Co-authored-by: github-actions <>
2022-04-01 12:12:08 +02:00
github-actions[bot]
284d728023 Autosync the updated translations (#1863)
Co-authored-by: github-actions <>
2022-03-25 01:21:43 +01:00
mp-bw
0796bf17ce Fix for missing token when checking for key connector migration (#1861) 2022-03-24 15:53:12 -04:00
github-actions[bot]
4bd06d2393 Bump version to 2.17.1 (#1859)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-03-22 12:41:49 -06:00
github-actions[bot]
a3a508eb83 Bump version to 2.17.0 (#1858)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-03-22 10:49:58 -06:00
Matt Portune
f10307c72d Remove verbose state & value storage debug logging (#1857) 2022-03-21 16:44:54 -04:00
Federico Maccaroni
840925c479 Added null checks for iOS crash OnActivated on KeyWindow (#1856) 2022-03-21 11:34:22 -04:00
github-actions[bot]
fdcb2d76c9 Bumped version to 2.16.5 (#1854)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-03-18 13:21:46 -07:00
jnolan912
4734fe4e43 Update ios Autofill page to match setting's name (#1354)
The option in the ios menu to get to autofill settings is called "Passwords" instead of "Passwords & Accounts"
2022-03-18 20:00:37 +00:00
Federico Maccaroni
383eee6ec7 Fixed flickering on iOS while loading collections for the collection crash hotfix (#1852) 2022-03-18 15:41:15 -03:00
github-actions[bot]
1d9671bc5c Autosync the updated translations (#1851)
Co-authored-by: github-actions <>
2022-03-18 01:18:33 +01:00
Federico Maccaroni
22b00bcb33 Fix iOS 15.4 crash from empty list to adding an item by awaiting after every header add; also added that on Settings just in case there is another crash scenario. (#1850) 2022-03-17 17:33:22 -03:00
Matt Portune
c1748acf39 Misc fixes for account switching (#1849)
* Misc fixes for account switching

* use unique bio integrity key in ShareExtension
2022-03-17 14:27:01 -04:00
Micaiah Martin
507c3faea1 Updated actions (#1848) 2022-03-17 09:24:42 -06:00
Chad Scharf
020a5c072d Update SECURITY.md (#1847)
* Update SECURITY.md

Add link to our HackerOne program for submitting potential security issues.

* Revise language on SECURITY.md
2022-03-15 15:54:45 -04:00
github-actions[bot]
c47aad0412 Bumped version to 2.16.4 (#1846)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-03-15 09:27:50 -07:00
Federico Maccaroni
7c83d7b37b Removed grouping from Settings to fix a crash on iOS 15.4 (#1845) 2022-03-15 10:19:34 -04:00
Federico Maccaroni
4d4e246a47 Fix #1745 crash on scroll of grouped collection view on iOS 15.4 beta (#1842) 2022-03-14 12:49:57 -04:00
github-actions[bot]
612e458071 Autosync the updated translations (#1839)
Co-authored-by: github-actions <>
2022-03-11 02:28:34 +01:00
Matt Portune
a2ec263116 fixes for font cutoff on samsung devices (#1838) 2022-03-10 13:55:48 -05:00
Micaiah Martin
5ade10d1fe Update input name to be consistent with other workflows (#1837) 2022-03-10 11:31:49 -07:00
Matt Portune
5008e1daa8 fixed issues with logging out inactive accounts (#1836) 2022-03-10 09:02:01 -05:00
Federico Maccaroni
ad7c656868 Prevent touches when root view is obscured by another screen on Android (#1835) 2022-03-10 09:55:58 -03:00
Joseph Flinn
bdd0ea007b Update hotfix release branch name to hotfix-rc (#1834) 2022-03-09 12:46:24 -08:00
Matt Portune
bf33f23c12 Fix for short profile Name value crashing app (#1833) 2022-03-09 09:00:04 -05:00
Matt Portune
c043528a16 fix for lock & logout message parsing issue (#1832) 2022-03-08 14:26:35 -05:00
Federico Maccaroni
fd74164f82 Remove Microsoft.AppCenter.Crashes from Core.csproj on FDroid on the build.yml (#1831) 2022-03-08 14:45:55 -03:00
113 changed files with 1420 additions and 765 deletions

View File

@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- name: Set up CLOC
run: |
@@ -36,7 +36,7 @@ jobs:
hotfix_branch_exists: ${{ steps.branch-check.outputs.hotfix_branch_exists }}
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- name: Check if special branches exist
id: branch-check
@@ -47,7 +47,7 @@ jobs:
echo "::set-output name=rc_branch_exists::0"
fi
if [[ $(git ls-remote --heads origin hotfix) ]]; then
if [[ $(git ls-remote --heads origin hotfix-rc) ]]; then
echo "::set-output name=hotfix_branch_exists::1"
else
echo "::set-output name=hotfix_branch_exists::0"
@@ -61,7 +61,7 @@ jobs:
needs: setup
steps:
- name: Set up MSBuild
uses: microsoft/setup-msbuild@c26a08ba26249b81327e26f6ef381897b6a8754d # v1
uses: microsoft/setup-msbuild@ab534842b4bdf384b8aaf93765dc6f721d9f5fab
- name: Print environment
run: |
@@ -72,7 +72,7 @@ jobs:
echo "GitHub event: $GITHUB_EVENT"
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- name: Decrypt secrets
env:
@@ -167,14 +167,14 @@ jobs:
shell: pwsh
- name: Upload Play Store .aab artifact
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.4
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: com.x8bit.bitwarden.aab
path: ./com.x8bit.bitwarden.aab
if-no-files-found: error
- name: Upload Play Store .apk artifact
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.4
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: com.x8bit.bitwarden.apk
path: ./com.x8bit.bitwarden.apk
@@ -186,7 +186,7 @@ jobs:
&& needs.setup.outputs.rc_branch_exists == 0
&& needs.setup.outputs.hotfix_branch_exists == 0)
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|| github.ref == 'refs/heads/hotfix'
|| github.ref == 'refs/heads/hotfix-rc'
run: |
PUBLISHER_PATH="$GITHUB_WORKSPACE/store/google/Publisher/bin/Release/netcoreapp3.1/Publisher.dll"
CREDS_PATH="$HOME/secrets/play_creds.json"
@@ -202,7 +202,7 @@ jobs:
runs-on: windows-2019
steps:
- name: Set up MSBuild
uses: microsoft/setup-msbuild@c26a08ba26249b81327e26f6ef381897b6a8754d # v1
uses: microsoft/setup-msbuild@ab534842b4bdf384b8aaf93765dc6f721d9f5fab
- name: Print environment
run: |
@@ -213,7 +213,7 @@ jobs:
echo "GitHub event: $GITHUB_EVENT"
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- name: Decrypt secrets
env:
@@ -241,6 +241,7 @@ jobs:
run: |
$androidPath = $($env:GITHUB_WORKSPACE + "/src/Android/Android.csproj");
$appPath = $($env:GITHUB_WORKSPACE + "/src/App/App.csproj");
$corePath = $($env:GITHUB_WORKSPACE + "/src/Core/Core.csproj");
$androidManifest = $($env:GITHUB_WORKSPACE + "/src/Android/Properties/AndroidManifest.xml");
@@ -306,6 +307,18 @@ jobs:
$appCenterNode.ParentNode.RemoveChild($appCenterNode);
$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);
shell: pwsh
- name: Restore packages
@@ -347,7 +360,7 @@ jobs:
shell: pwsh
- name: Upload F-Droid .apk artifact
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.4
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: com.x8bit.bitwarden-fdroid.apk
path: ./com.x8bit.bitwarden-fdroid.apk
@@ -368,16 +381,16 @@ jobs:
echo "GitHub event: $GITHUB_EVENT"
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- name: Login to Azure - Prod Subscription
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf
with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets
id: retrieve-secrets
uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f
with:
keyvault: "bitwarden-prod-kv"
secrets: "appcenter-ios-token"
@@ -399,7 +412,8 @@ jobs:
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output $HOME/secrets/dist_extension.mobileprovision ./.github/secrets/dist_extension.mobileprovision.gpg
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output $HOME/secrets/dist_share_extension.mobileprovision ./.github/secrets/dist_share_extension.mobileprovision.gpg
--output $HOME/secrets/dist_share_extension.mobileprovision \
./.github/secrets/dist_share_extension.mobileprovision.gpg
shell: bash
- name: Increment version
@@ -495,7 +509,7 @@ jobs:
-exportOptionsPlist $EXPORT_OPTIONS_PATH
shell: bash
- name: Copy all dSYMs files to upload
- name: Copy all dSYMs files to upload
run: |
ARCHIVE_DSYMS_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive/dSYMs"
EXPORT_PATH="./bitwarden-export"
@@ -504,7 +518,7 @@ jobs:
shell: bash
- name: Upload App Store .ipa & dSYMs artifacts
uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.4
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535
with:
name: Bitwarden iOS
path: |
@@ -514,15 +528,12 @@ jobs:
- name: Install AppCenter CLI
if: |
(github.ref == 'refs/heads/master'
&& needs.setup.outputs.rc_branch_exists == 0
&& needs.setup.outputs.hotfix_branch_exists == 0)
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|| github.ref == 'refs/heads/hotfix'
uses: actions/setup-node@v2
with:
node-version: '14'
- run: npm install -g appcenter-cli
(github.ref == 'refs/heads/master'
&& needs.setup.outputs.rc_branch_exists == 0
&& needs.setup.outputs.hotfix_branch_exists == 0)
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|| github.ref == 'refs/heads/hotfix-rc'
run: npm install -g appcenter-cli
- name: Upload dSYMs to App Center
if: |
@@ -530,10 +541,10 @@ jobs:
&& needs.setup.outputs.rc_branch_exists == 0
&& needs.setup.outputs.hotfix_branch_exists == 0)
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|| github.ref == 'refs/heads/hotfix'
|| github.ref == 'refs/heads/hotfix-rc'
env:
APPCENTER_IOS_TOKEN: ${{ steps.retrieve-secrets.outputs.appcenter-ios-token }}
run: appcenter crashes upload-symbols -a kspearrin/bitwarden -s "./bitwarden-export/dSYMs" --token $APPCENTER_IOS_TOKEN
run: appcenter crashes upload-symbols -a bitwarden/bitwarden -s "./bitwarden-export/dSYMs" --token $APPCENTER_IOS_TOKEN
shell: bash
- name: Deploy to App Store
@@ -542,7 +553,7 @@ jobs:
&& needs.setup.outputs.rc_branch_exists == 0
&& needs.setup.outputs.hotfix_branch_exists == 0)
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|| github.ref == 'refs/heads/hotfix'
|| github.ref == 'refs/heads/hotfix-rc'
env:
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
@@ -564,22 +575,22 @@ jobs:
_CROWDIN_PROJECT_ID: "269690"
steps:
- name: Checkout repo
uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846
- name: Login to Azure
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf
with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets
id: retrieve-secrets
uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f
with:
keyvault: "bitwarden-prod-kv"
secrets: "crowdin-api-token"
- name: Upload Sources
uses: crowdin/github-action@e39093fd75daae7859c68eded4b43d42ec78d8ea # v1.3.2
uses: crowdin/github-action@9237b4cb361788dfce63feb2e2f15c09e2fe7415
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
@@ -605,7 +616,7 @@ jobs:
if: |
(github.ref == 'refs/heads/master')
|| (github.ref == 'refs/heads/rc')
|| (github.ref == 'refs/heads/hotfix')
|| (github.ref == 'refs/heads/hotfix-rc')
env:
CLOC_STATUS: ${{ needs.cloc.result }}
ANDROID_STATUS: ${{ needs.android.result }}
@@ -626,21 +637,21 @@ jobs:
fi
- name: Login to Azure - Prod Subscription
uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a
uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf
if: failure()
with:
creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }}
- name: Retrieve secrets
id: retrieve-secrets
uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403
uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f
if: failure()
with:
keyvault: "bitwarden-prod-kv"
secrets: "devops-alerts-slack-webhook-url"
- name: Notify Slack on failure
uses: act10ns/slack@e4e71685b9b239384b0f676a63c32367f59c2522 # v1.2.2
uses: act10ns/slack@da3191ebe2e67f49b46880b4633f5591a96d1d33
if: failure()
env:
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}

View File

@@ -12,7 +12,7 @@ on:
options:
- Initial Release
- Redeploy
- dry-run
- Dry Run
jobs:
release:
@@ -22,11 +22,11 @@ jobs:
branch-name: ${{ steps.branch.outputs.branch-name }}
steps:
- name: Branch check
if: github.event.inputs.release_type != 'dry-run'
if: github.event.inputs.release_type != 'Dry Run'
run: |
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix" ]]; then
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then
echo "==================================="
echo "[!] Can only release from the 'rc' or 'hotfix' branches"
echo "[!] Can only release from the 'rc' or 'hotfix-rc' branches"
echo "==================================="
exit 1
fi
@@ -75,7 +75,7 @@ jobs:
run: zip -r Bitwarden\ iOS.zip Bitwarden\ iOS
- name: Create release
if: github.event.inputs.release_type != 'dry-run'
if: github.event.inputs.release_type != 'Dry Run'
uses: ncipollo/release-action@40bb172bd05f266cf9ba4ff965cb61e9ee5f6d01 # v1.9.0
with:
artifacts: "./com.x8bit.bitwarden.aab/com.x8bit.bitwarden.aab,
@@ -171,5 +171,5 @@ jobs:
cd $GITHUB_WORKSPACE
- name: Deploy to gh-pages
if: github.event.inputs.release_type != 'dry-run'
if: github.event.inputs.release_type != 'Dry Run'
run: npm run deploy

View File

@@ -1,39 +1,11 @@
Bitwarden believes that working with security researchers across the globe is crucial to keeping our
users safe. If you believe you've found a security issue in our product or service, we encourage you to
notify us. We welcome working with you to resolve the issue promptly. Thanks in advance!
Bitwarden believes that working with security researchers across the globe is crucial to keeping our users safe. If you believe you've found a security issue in our product or service, we encourage you to please submit a report through our [HackerOne Program](https://hackerone.com/bitwarden/). We welcome working with you to resolve the issue promptly. Thanks in advance!
# Disclosure Policy
- Let us know as soon as possible upon discovery of a potential security issue, and we'll make every
effort to quickly resolve the issue.
- Provide us a reasonable amount of time to resolve the issue before any disclosure to the public or a
third-party. We may publicly disclose the issue before resolving it, if appropriate.
- Make a good faith effort to avoid privacy violations, destruction of data, and interruption or
degradation of our service. Only interact with accounts you own or with explicit permission of the
account holder.
- If you would like to encrypt your report, please use the PGP key with long ID
`0xDE6887086F892325FEC04CC0D847525B6931381F` (available in the public keyserver pool).
# In-scope
- Security issues in any current release of Bitwarden. This includes the web vault, browser extension,
and mobile apps (iOS and Android). Product downloads are available at https://bitwarden.com. Source
code is available at https://github.com/bitwarden.
# Exclusions
The following bug classes are out-of scope:
- Bugs that are already reported on any of Bitwarden's issue trackers (https://github.com/bitwarden),
or that we already know of. Note that some of our issue tracking is private.
- Issues in an upstream software dependency (ex: Xamarin, ASP.NET) which are already reported to the
upstream maintainer.
- Attacks requiring physical access to a user's device.
- Self-XSS
- Issues related to software or protocols not under Bitwarden's control
- Vulnerabilities in outdated versions of Bitwarden
- Missing security best practices that do not directly lead to a vulnerability
- Issues that do not have any impact on the general public
- Let us know as soon as possible upon discovery of a potential security issue, and we'll make every effort to quickly resolve the issue.
- Provide us a reasonable amount of time to resolve the issue before any disclosure to the public or a third-party. We may publicly disclose the issue before resolving it, if appropriate.
- Make a good faith effort to avoid privacy violations, destruction of data, and interruption or degradation of our service. Only interact with accounts you own or with explicit permission of the account holder.
- If you would like to encrypt your report, please use the PGP key with long ID `0xDE6887086F892325FEC04CC0D847525B6931381F` (available in the public keyserver pool).
While researching, we'd like to ask you to refrain from:
@@ -42,4 +14,8 @@ While researching, we'd like to ask you to refrain from:
- Social engineering (including phishing) of Bitwarden staff or contractors
- Any physical attempts against Bitwarden property or data centers
# We want to help you!
If you have something that you feel is close to exploitation, or if you'd like some information regarding the internal API, or generally have any questions regarding the app that would help in your efforts, please email us at https://bitwarden.com/contact and ask for that information. As stated above, Bitwarden wants to help you find issues, and is more than willing to help.
Thank you for helping keep Bitwarden and our users safe!

View File

@@ -84,7 +84,7 @@
<PackageReference Include="Xamarin.AndroidX.MediaRouter" Version="1.2.5.2" />
<PackageReference Include="Xamarin.AndroidX.Migration" Version="1.0.8" />
<PackageReference Include="Xamarin.Essentials">
<Version>1.7.1</Version>
<Version>1.7.2</Version>
</PackageReference>
<PackageReference Include="Xamarin.Firebase.Messaging">
<Version>122.0.0</Version>

View File

@@ -74,6 +74,12 @@ namespace Bit.Droid
var appCenterTask = appCenterHelper.InitAsync();
#endif
var toplayout = Window?.DecorView?.RootView;
if (toplayout != null)
{
toplayout.FilterTouchesWhenObscured = true;
}
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
Xamarin.Forms.Forms.Init(this, savedInstanceState);
_appOptions = GetOptions();

View File

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

View File

@@ -1,13 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Android.OS;
using Android.Security.Keystore;
using Bit.Core.Abstractions;
using Java.Security;
using Javax.Crypto;
#if !FDROID
using Microsoft.AppCenter.Crashes;
#endif
namespace Bit.Droid.Services
{
@@ -43,23 +43,22 @@ namespace Bit.Droid.Services
public Task<bool> ValidateIntegrityAsync(string bioIntegrityKey = null)
{
// bioIntegrityKey used in iOS only
if (Build.VERSION.SdkInt < BuildVersionCodes.M)
{
return Task.FromResult(true);
}
_keystore.Load(null);
IKey key = _keystore.GetKey(KeyName, null);
Cipher cipher = Cipher.GetInstance(Transformation);
if (key == null || cipher == null)
{
return Task.FromResult(true);
}
try
{
_keystore.Load(null);
var key = _keystore.GetKey(KeyName, null);
var cipher = Cipher.GetInstance(Transformation);
if (key == null || cipher == null)
{
return Task.FromResult(true);
}
cipher.Init(CipherMode.EncryptMode, key);
}
catch (KeyPermanentlyInvalidatedException e)
@@ -75,6 +74,9 @@ namespace Bit.Droid.Services
catch (InvalidKeyException e)
{
// Fallback for old bitwarden users without a key
#if !FDROID
Crashes.TrackError(e);
#endif
CreateKey();
}
@@ -95,10 +97,13 @@ namespace Bit.Droid.Services
keyGen.Init(keyGenSpec);
keyGen.GenerateKey();
}
catch
catch (Exception e)
{
// Catch silently to allow biometrics to function on devices that are in a state where key generation
// is not functioning
#if !FDROID
Crashes.TrackError(e);
#endif
}
}
}

View File

@@ -674,7 +674,7 @@ namespace Bit.Droid.Services
else
{
var data = new Intent();
if (cipher == null)
if (cipher?.Login == null)
{
data.PutExtra("canceled", "true");
}
@@ -734,6 +734,11 @@ namespace Bit.Droid.Services
return Accessibility.AccessibilityHelpers.OverlayPermitted();
}
public bool HasAutofillService()
{
return true;
}
public void OpenAccessibilityOverlayPermissionSettings()
{
var activity = (MainActivity)CrossCurrentActivity.Current.Activity;
@@ -943,5 +948,10 @@ namespace Bit.Droid.Services
var activity = CrossCurrentActivity.Current?.Activity as MainActivity;
return activity?.Resources?.Configuration?.FontScale ?? 1;
}
public async Task OnAccountSwitchCompleteAsync()
{
// for any Android-specific cleanup required after switching accounts
}
}
}

View File

@@ -35,6 +35,7 @@ namespace Bit.App.Abstractions
void Background();
bool AutofillAccessibilityServiceRunning();
bool AutofillAccessibilityOverlayPermitted();
bool HasAutofillService();
bool AutofillServiceEnabled();
void DisableAutofillService();
bool AutofillServicesEnabled();
@@ -46,5 +47,6 @@ namespace Bit.App.Abstractions
void CloseMainApp();
bool SupportsFido2();
float GetSystemFontSizeScale();
Task OnAccountSwitchCompleteAsync();
}
}

View File

@@ -16,10 +16,10 @@
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="4.4.0" />
<PackageReference Include="Plugin.Fingerprint" Version="2.1.4" />
<PackageReference Include="SkiaSharp.Views.Forms" Version="2.80.3" />
<PackageReference Include="Xamarin.CommunityToolkit" Version="2.0.0" />
<PackageReference Include="Xamarin.Essentials" Version="1.7.1" />
<PackageReference Include="Xamarin.CommunityToolkit" Version="2.0.1" />
<PackageReference Include="Xamarin.Essentials" Version="1.7.2" />
<PackageReference Include="Xamarin.FFImageLoading.Forms" Version="2.4.11.982" />
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2337" />
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2401" />
<PackageReference Include="ZXing.Net.Mobile" Version="2.4.1" />
<PackageReference Include="ZXing.Net.Mobile.Forms" Version="2.4.1" />
</ItemGroup>

View File

@@ -73,8 +73,9 @@ namespace Bit.App
}
else if (message.Command == "locked")
{
var (userId, userInitiated) =
message.Data as Tuple<string, bool> ?? new Tuple<string, bool>(null, false);
var extras = message.Data as Tuple<string, bool>;
var userId = extras?.Item1;
var userInitiated = extras?.Item2 ?? false;
Device.BeginInvokeOnMainThread(async () => await LockedAsync(userId, userInitiated));
}
else if (message.Command == "lockVault")
@@ -83,8 +84,10 @@ namespace Bit.App
}
else if (message.Command == "logout")
{
var (userId, userInitiated, expired) =
message.Data as Tuple<string, bool, bool> ?? new Tuple<string, bool, bool>(null, true, false);
var extras = message.Data as Tuple<string, bool, bool>;
var userId = extras?.Item1;
var userInitiated = extras?.Item2 ?? true;
var expired = extras?.Item3 ?? false;
Device.BeginInvokeOnMainThread(async () => await LogOutAsync(userId, userInitiated, expired));
}
else if (message.Command == "loggedOut")
@@ -425,7 +428,7 @@ namespace Bit.App
});
}
private async Task LockedAsync(string userId, bool autoPromptBiometric)
private async Task LockedAsync(string userId, bool userInitiated)
{
if (!await _stateService.IsActiveAccountAsync(userId))
{
@@ -433,6 +436,7 @@ namespace Bit.App
return;
}
var autoPromptBiometric = !userInitiated;
if (autoPromptBiometric && Device.RuntimePlatform == Device.iOS)
{
var vaultTimeout = await _stateService.GetVaultTimeoutAsync();

View File

@@ -59,26 +59,26 @@
Grid.Row="0"
Text="{Binding AccountView.Email}"
IsVisible="{Binding IsActive}"
StyleClass="list-title"
StyleClass="accountlist-title, accountlist-title-platform"
LineBreakMode="TailTruncation" />
<Label
Grid.Row="0"
Text="{Binding AccountView.Email}"
IsVisible="{Binding IsActive, Converter={StaticResource inverseBool}}"
StyleClass="list-title"
StyleClass="accountlist-title, accountlist-title-platform"
TextColor="{DynamicResource MutedColor}"
LineBreakMode="TailTruncation" />
<Label
Grid.Row="1"
IsVisible="{Binding ShowHostname}"
Text="{Binding AccountView.Hostname}"
StyleClass="list-sub"
StyleClass="accountlist-sub, accountlist-sub-platform"
LineBreakMode="TailTruncation" />
<Label
Grid.Row="2"
Text="{u:I18n AccountUnlocked}"
IsVisible="{Binding IsUnlockedAndNotActive}"
StyleClass="list-sub"
StyleClass="accountlist-sub, accountlist-sub-platform"
FontAttributes="Italic"
TextTransform="Lowercase"
LineBreakMode="TailTruncation" />
@@ -86,7 +86,7 @@
Grid.Row="2"
Text="{u:I18n AccountLocked}"
IsVisible="{Binding IsLockedAndNotActive}"
StyleClass="list-sub"
StyleClass="accountlist-sub, accountlist-sub-platform"
FontAttributes="Italic"
TextTransform="Lowercase"
LineBreakMode="TailTruncation" />
@@ -94,7 +94,7 @@
Grid.Row="2"
Text="{u:I18n AccountLoggedOut}"
IsVisible="{Binding IsLoggedOutAndNotActive}"
StyleClass="list-sub"
StyleClass="accountlist-sub, accountlist-sub-platform"
FontAttributes="Italic"
TextTransform="Lowercase"
LineBreakMode="TailTruncation" />
@@ -144,7 +144,7 @@
AutomationProperties.IsInAccessibleTree="False" />
<Label
Text="{u:I18n AddAccount}"
StyleClass="list-title"
StyleClass="accountlist-title, accountlist-title-platform"
LineBreakMode="TailTruncation"
VerticalOptions="Center"
Grid.Column="1" />

View File

@@ -62,6 +62,10 @@ namespace Bit.App.Controls
upperData = _data.ToUpper();
chars = GetFirstLetters(upperData, 2);
}
else
{
chars = upperData = _data.ToUpper();
}
var bgColor = StringToColor(upperData);
var textColor = Color.White;
@@ -122,7 +126,7 @@ namespace Bit.App.Controls
{
return data.Substring(0, 2);
}
return null;
return data;
}
private Color StringToColor(string str)

View File

@@ -41,8 +41,11 @@ namespace Bit.App.Pages
public async Task InitAsync()
{
var history = await _passwordGenerationService.GetHistoryAsync();
History.ResetWithRange(history ?? new List<GeneratedPasswordHistory>());
ShowNoData = History.Count == 0;
Device.BeginInvokeOnMainThread(() =>
{
History.ResetWithRange(history ?? new List<GeneratedPasswordHistory>());
ShowNoData = History.Count == 0;
});
}
public async Task ClearAsync()

View File

@@ -256,23 +256,24 @@
x:Name="_btnOptions"
StyleClass="box-row-button"
TextColor="{DynamicResource PrimaryColor}"
Margin="0" />
Margin="0"
Clicked="ToggleOptions_Clicked"/>
<controls:IconButton
x:Name="_btnOptionsUp"
Text="{Binding Source={x:Static core:BitwardenIcons.ChevronUp}}"
StyleClass="box-row-button"
TextColor="{DynamicResource PrimaryColor}"
Clicked="ToggleOptions_Clicked"
IsVisible="False" />
IsVisible="{Binding ShowOptions}" />
<controls:IconButton
x:Name="_btnOptionsDown"
Text="{Binding Source={x:Static core:BitwardenIcons.AngleDown}}"
StyleClass="box-row-button"
TextColor="{DynamicResource PrimaryColor}"
Clicked="ToggleOptions_Clicked"
IsVisible="False" />
IsVisible="{Binding ShowOptions, Converter={StaticResource inverseBool}}" />
</StackLayout>
<StackLayout IsVisible="True">
<StackLayout IsVisible="{Binding ShowOptions}">
<StackLayout
StyleClass="box-row"
Margin="0,10,0,0">

View File

@@ -53,10 +53,9 @@ namespace Bit.App.Pages
_vm.SegmentedButtonFontSize = 13;
_vm.SegmentedButtonMargins = new Thickness(0, 10, 0, 0);
_vm.EditorMargins = new Thickness(0, 5, 0, 0);
// Review this when https://github.com/bitwarden/mobile/pull/1454 workaround can be reverted
//_btnOptions.WidthRequest = 70;
//_btnOptionsDown.WidthRequest = 30;
//_btnOptionsUp.WidthRequest = 30;
_btnOptions.WidthRequest = 70;
_btnOptionsDown.WidthRequest = 30;
_btnOptionsUp.WidthRequest = 30;
}
else if (Device.RuntimePlatform == Device.iOS)
{

View File

@@ -0,0 +1,6 @@
namespace Bit.App.Pages
{
public interface ISendGroupingsPageListItem
{
}
}

View File

@@ -73,7 +73,29 @@
</controls:ExtendedStackLayout>
</DataTemplate>
<DataTemplate
x:Key="headerTemplate"
x:DataType="pages:SendGroupingsPageHeaderListItem">
<StackLayout
Spacing="0" Padding="0" VerticalOptions="FillAndExpand"
StyleClass="list-row-header-container, list-row-header-container-platform">
<BoxView
StyleClass="list-section-separator-top, list-section-separator-top-platform" />
<StackLayout StyleClass="list-row-header, list-row-header-platform">
<Label
Text="{Binding Title}"
StyleClass="list-header, list-header-platform" />
<Label
Text="{Binding ItemCount}"
StyleClass="list-header-sub" />
</StackLayout>
<BoxView
StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform" />
</StackLayout>
</DataTemplate>
<pages:SendGroupingsPageListItemSelector x:Key="sendListItemDataTemplateSelector"
HeaderTemplate="{StaticResource headerTemplate}"
SendTemplate="{StaticResource sendTemplate}"
GroupTemplate="{StaticResource sendGroupTemplate}" />
@@ -114,33 +136,9 @@
ItemsSource="{Binding GroupedSends}"
VerticalOptions="FillAndExpand"
ItemTemplate="{StaticResource sendListItemDataTemplateSelector}"
IsGrouped="True"
SelectionMode="Single"
SelectionChanged="RowSelected"
StyleClass="list, list-platform">
<CollectionView.GroupHeaderTemplate>
<DataTemplate x:DataType="pages:SendGroupingsPageListGroup">
<StackLayout
Spacing="0" Padding="0" VerticalOptions="FillAndExpand"
StyleClass="list-row-header-container, list-row-header-container-platform">
<BoxView
StyleClass="list-section-separator-top, list-section-separator-top-platform"
IsVisible="{Binding First, Converter={StaticResource inverseBool}}" />
<StackLayout StyleClass="list-row-header, list-row-header-platform">
<Label
Text="{Binding Name}"
StyleClass="list-header, list-header-platform" />
<Label
Text="{Binding ItemCount}"
StyleClass="list-header-sub" />
</StackLayout>
<BoxView
StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform" />
</StackLayout>
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
</controls:ExtendedCollectionView>
StyleClass="list, list-platform" />
</RefreshView>
</StackLayout>
</ResourceDictionary>

View File

@@ -0,0 +1,14 @@
namespace Bit.App.Pages
{
public class SendGroupingsPageHeaderListItem : ISendGroupingsPageListItem
{
public SendGroupingsPageHeaderListItem(string title, string itemCount)
{
Title = title;
ItemCount = itemCount;
}
public string Title { get; }
public string ItemCount { get; }
}
}

View File

@@ -5,7 +5,7 @@ using Bit.Core.Models.View;
namespace Bit.App.Pages
{
public class SendGroupingsPageListItem
public class SendGroupingsPageListItem : ISendGroupingsPageListItem
{
private string _icon;
private string _name;

View File

@@ -4,11 +4,17 @@ namespace Bit.App.Pages
{
public class SendGroupingsPageListItemSelector : DataTemplateSelector
{
public DataTemplate HeaderTemplate { get; set; }
public DataTemplate SendTemplate { get; set; }
public DataTemplate GroupTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
if (item is SendGroupingsPageHeaderListItem)
{
return HeaderTemplate;
}
if (item is SendGroupingsPageListItem listItem)
{
return listItem.Send != null ? SendTemplate : GroupTemplate;

View File

@@ -10,6 +10,7 @@ using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Models.View;
using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Essentials;
using Xamarin.Forms;
using DeviceType = Bit.Core.Enums.DeviceType;
@@ -48,7 +49,7 @@ namespace Bit.App.Pages
Loading = true;
PageTitle = AppResources.Send;
GroupedSends = new ExtendedObservableCollection<SendGroupingsPageListGroup>();
GroupedSends = new ObservableRangeCollection<ISendGroupingsPageListItem>();
RefreshCommand = new Command(async () =>
{
Refreshing = true;
@@ -103,7 +104,7 @@ namespace Bit.App.Pages
get => _showList;
set => SetProperty(ref _showList, value);
}
public ExtendedObservableCollection<SendGroupingsPageListGroup> GroupedSends { get; set; }
public ObservableRangeCollection<ISendGroupingsPageListItem> GroupedSends { get; set; }
public Command RefreshCommand { get; set; }
public Command<SendView> SendOptionsCommand { get; set; }
public bool LoadedOnce { get; set; }
@@ -175,7 +176,49 @@ namespace Bit.App.Pages
MainPage ? AppResources.AllSends : AppResources.Sends, sendsListItems.Count,
uppercaseGroupNames, !MainPage));
}
GroupedSends.ResetWithRange(groupedSends);
// TODO: refactor this
if (Device.RuntimePlatform == Device.Android
||
GroupedSends.Any())
{
var items = new List<ISendGroupingsPageListItem>();
foreach (var itemGroup in groupedSends)
{
items.Add(new SendGroupingsPageHeaderListItem(itemGroup.Name, itemGroup.ItemCount));
items.AddRange(itemGroup);
}
GroupedSends.ReplaceRange(items);
}
else
{
// HACK: we need this on iOS, so that it doesn't crash when adding coming from an empty list
var first = true;
var items = new List<ISendGroupingsPageListItem>();
foreach (var itemGroup in groupedSends)
{
if (!first)
{
items.Add(new SendGroupingsPageHeaderListItem(itemGroup.Name, itemGroup.ItemCount));
}
else
{
first = false;
}
items.AddRange(itemGroup);
}
if (groupedSends.Any())
{
GroupedSends.ReplaceRange(new List<ISendGroupingsPageListItem> { new SendGroupingsPageHeaderListItem(groupedSends[0].Name, groupedSends[0].ItemCount) });
GroupedSends.AddRange(items);
}
else
{
GroupedSends.Clear();
}
}
}
finally
{

View File

@@ -192,7 +192,8 @@ namespace Bit.App.Pages
public void UpdateEnabled()
{
AutofillServiceToggled = _deviceActionService.AutofillServiceEnabled();
AutofillServiceToggled =
_deviceActionService.HasAutofillService() && _deviceActionService.AutofillServiceEnabled();
AccessibilityToggled = _deviceActionService.AutofillAccessibilityServiceRunning();
DrawOverToggled = _deviceActionService.AutofillAccessibilityOverlayPermitted();
}

View File

@@ -0,0 +1,6 @@
namespace Bit.App.Pages
{
public interface ISettingsPageListItem
{
}
}

View File

@@ -82,8 +82,26 @@
</controls:ExtendedStackLayout>
</DataTemplate>
<DataTemplate
x:Key="headerTemplate"
x:DataType="pages:SettingsPageHeaderListItem">
<StackLayout
Padding="0" Spacing="0" VerticalOptions="FillAndExpand"
StyleClass="list-row-header-container, list-row-header-container-platform">
<BoxView
StyleClass="list-section-separator-top, list-section-separator-top-platform" />
<StackLayout StyleClass="list-row-header, list-row-header-platform">
<Label
Text="{Binding Title}"
StyleClass="list-header, list-header-platform" />
</StackLayout>
<BoxView StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform" />
</StackLayout>
</DataTemplate>
<pages:SettingsPageListItemSelector
x:Key="listItemDataTemplateSelector"
HeaderTemplate="{StaticResource headerTemplate}"
RegularTemplate="{StaticResource regularTemplate}"
TimePickerTemplate="{StaticResource timePickerTemplate}" />
</ResourceDictionary>
@@ -93,28 +111,8 @@
ItemsSource="{Binding GroupedItems}"
VerticalOptions="FillAndExpand"
ItemTemplate="{StaticResource listItemDataTemplateSelector}"
IsGrouped="True"
SelectionMode="Single"
SelectionChanged="RowSelected"
StyleClass="list, list-platform">
<CollectionView.GroupHeaderTemplate>
<DataTemplate x:DataType="pages:SettingsPageListGroup">
<StackLayout
Padding="0" Spacing="0" VerticalOptions="FillAndExpand"
StyleClass="list-row-header-container, list-row-header-container-platform">
<BoxView
StyleClass="list-section-separator-top, list-section-separator-top-platform"
IsVisible="{Binding First, Converter={StaticResource inverseBool}}" />
<StackLayout StyleClass="list-row-header, list-row-header-platform">
<Label
Text="{Binding Name}"
StyleClass="list-header, list-header-platform" />
</StackLayout>
<BoxView StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform" />
</StackLayout>
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
</controls:ExtendedCollectionView>
StyleClass="list, list-platform" />
</pages:BaseContentPage>

View File

@@ -0,0 +1,12 @@
namespace Bit.App.Pages
{
public class SettingsPageHeaderListItem : ISettingsPageListItem
{
public SettingsPageHeaderListItem(string title)
{
Title = title;
}
public string Title { get; }
}
}

View File

@@ -1,12 +1,11 @@
using System;
using Bit.App.Resources;
using Bit.App.Utilities;
using System.Collections.Generic;
using Xamarin.Forms;
namespace Bit.App.Pages
{
public class SettingsPageListItem
public class SettingsPageListItem : ISettingsPageListItem
{
public string Icon { get; set; }
public string Name { get; set; }

View File

@@ -4,21 +4,19 @@ namespace Bit.App.Pages
{
public class SettingsPageListItemSelector : DataTemplateSelector
{
public DataTemplate HeaderTemplate { get; set; }
public DataTemplate RegularTemplate { get; set; }
public DataTemplate TimePickerTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
if (item is SettingsPageHeaderListItem)
{
return HeaderTemplate;
}
if (item is SettingsPageListItem listItem)
{
if (listItem.ShowTimeInput)
{
return TimePickerTemplate;
}
else
{
return RegularTemplate;
}
return listItem.ShowTimeInput ? TimePickerTemplate : RegularTemplate;
}
return null;
}

View File

@@ -10,6 +10,7 @@ using Bit.Core.Enums;
using Bit.Core.Models.Domain;
using Xamarin.Forms;
using ZXing.Client.Result;
using Xamarin.CommunityToolkit.ObjectModel;
namespace Bit.App.Pages
{
@@ -79,11 +80,11 @@ namespace Bit.App.Pages
_keyConnectorService = ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService");
_clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
GroupedItems = new ExtendedObservableCollection<SettingsPageListGroup>();
GroupedItems = new ObservableRangeCollection<ISettingsPageListItem>();
PageTitle = AppResources.Settings;
}
public ExtendedObservableCollection<SettingsPageListGroup> GroupedItems { get; set; }
public ObservableRangeCollection<ISettingsPageListItem> GroupedItems { get; set; }
public async Task InitAsync()
{
@@ -501,7 +502,9 @@ namespace Bit.App.Pages
new SettingsPageListItem { Name = AppResources.RateTheApp },
new SettingsPageListItem { Name = AppResources.DeleteAccount }
};
GroupedItems.ResetWithRange(new List<SettingsPageListGroup>
// TODO: improve this. Leaving this as is to reduce error possibility on the hotfix.
var settingsListGroupItems = new List<SettingsPageListGroup>()
{
new SettingsPageListGroup(autofillItems, AppResources.Autofill, doUpper, true),
new SettingsPageListGroup(manageItems, AppResources.Manage, doUpper),
@@ -509,7 +512,50 @@ namespace Bit.App.Pages
new SettingsPageListGroup(accountItems, AppResources.Account, doUpper),
new SettingsPageListGroup(toolsItems, AppResources.Tools, doUpper),
new SettingsPageListGroup(otherItems, AppResources.Other, doUpper)
});
};
// TODO: refactor this
if (Device.RuntimePlatform == Device.Android
||
GroupedItems.Any())
{
var items = new List<ISettingsPageListItem>();
foreach (var itemGroup in settingsListGroupItems)
{
items.Add(new SettingsPageHeaderListItem(itemGroup.Name));
items.AddRange(itemGroup);
}
GroupedItems.ReplaceRange(items);
}
else
{
// HACK: we need this on iOS, so that it doesn't crash when adding coming from an empty list
var first = true;
var items = new List<ISettingsPageListItem>();
foreach (var itemGroup in settingsListGroupItems)
{
if (!first)
{
items.Add(new SettingsPageHeaderListItem(itemGroup.Name));
}
else
{
first = false;
}
items.AddRange(itemGroup);
}
if (settingsListGroupItems.Any())
{
GroupedItems.ReplaceRange(new List<ISettingsPageListItem> { new SettingsPageHeaderListItem(settingsListGroupItems[0].Name) });
GroupedItems.AddRange(items);
}
else
{
GroupedItems.Clear();
}
}
}
private bool IncludeLinksWithSubscriptionInfo()

View File

@@ -732,7 +732,6 @@
<BoxView StyleClass="box-row-separator" />
</StackLayout>
<controls:RepeaterView
x:Name="_collectionsRepeaterView"
ItemsSource="{Binding Collections}"
IsVisible="{Binding HasCollections}">
<controls:RepeaterView.ItemTemplate>

View File

@@ -51,7 +51,6 @@ namespace Bit.App.Pages
_vm.CipherId = cipherId;
_vm.FolderId = folderId == "none" ? null : folderId;
_vm.CollectionIds = collectionId != null ? new HashSet<string>(new List<string> { collectionId }) : null;
_vm.CollectionsRepeaterView = _collectionsRepeaterView;
_vm.Type = type;
_vm.DefaultName = name ?? appOptions?.SaveName;
_vm.DefaultUri = uri ?? appOptions?.Uri;
@@ -171,7 +170,6 @@ namespace Bit.App.Pages
{
RequestFocus(_nameEntry);
}
_scrollView.Scrolled += (sender, args) => _vm.HandleScroll();
});
// Hide password reprompt option if using key connector
_passwordPrompt.IsVisible = !await _keyConnectorService.GetUsesKeyConnector();

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Bit.App.Abstractions;
using Bit.App.Controls;
using Bit.App.Models;
using Bit.App.Resources;
using Bit.Core;
@@ -44,7 +43,6 @@ namespace Bit.App.Pages
private int _ownershipSelectedIndex;
private bool _hasCollections;
private string _previousCipherId;
private DateTime _lastHandledScrollTime;
private List<Core.Models.View.CollectionView> _writeableCollections;
private string[] _additionalCipherProperties = new string[]
{
@@ -168,7 +166,7 @@ namespace Bit.App.Pages
public ExtendedObservableCollection<LoginUriView> Uris { get; set; }
public ExtendedObservableCollection<AddEditPageFieldViewModel> Fields { get; set; }
public ExtendedObservableCollection<CollectionViewModel> Collections { get; set; }
public RepeaterView CollectionsRepeaterView { get; set; }
public int TypeSelectedIndex
{
get => _typeSelectedIndex;
@@ -821,30 +819,13 @@ namespace Bit.App.Pages
{
var cols = _writeableCollections.Where(c => c.OrganizationId == Cipher.OrganizationId)
.Select(c => new CollectionViewModel { Collection = c }).ToList();
HasCollections = cols.Any();
Collections.ResetWithRange(cols);
Collections = new ExtendedObservableCollection<CollectionViewModel>(cols);
}
else
{
HasCollections = false;
Collections.ResetWithRange(new List<CollectionViewModel>());
Collections = new ExtendedObservableCollection<CollectionViewModel>(new List<CollectionViewModel>());
}
}
public void HandleScroll()
{
// workaround for https://github.com/xamarin/Xamarin.Forms/issues/13607
// required for org ownership/collections to render properly in XF4.5+
if (!HasCollections ||
EditMode ||
(DateTime.Now - _lastHandledScrollTime < TimeSpan.FromMilliseconds(200)))
{
return;
}
CollectionsRepeaterView.ItemsSource = Collections;
_lastHandledScrollTime = DateTime.Now;
HasCollections = Collections.Any();
}
private void TriggerCipherChanged()

View File

@@ -29,8 +29,28 @@
ButtonCommand="{Binding BindingContext.CipherOptionsCommand, Source={x:Reference _page}}"
WebsiteIconsEnabled="{Binding BindingContext.WebsiteIconsEnabled, Source={x:Reference _page}}" />
</DataTemplate>
<DataTemplate
x:Key="headerTemplate"
x:DataType="pages:GroupingsPageHeaderListItem">
<StackLayout
Spacing="0" Padding="0" VerticalOptions="FillAndExpand"
StyleClass="list-row-header-container, list-row-header-container-platform">
<BoxView
StyleClass="list-section-separator-top, list-section-separator-top-platform" />
<StackLayout StyleClass="list-row-header, list-row-header-platform">
<Label
Text="{Binding Title}"
StyleClass="list-header, list-header-platform" />
<Label
Text="{Binding ItemCount}"
StyleClass="list-header-sub" />
</StackLayout>
</StackLayout>
</DataTemplate>
<pages:GroupingsPageListItemSelector x:Key="listItemDataTemplateSelector"
HeaderTemplate="{StaticResource headerTemplate}"
CipherTemplate="{StaticResource cipherTemplate}" />
<StackLayout x:Key="mainLayout" x:Name="_mainLayout">
@@ -52,30 +72,9 @@
ItemsSource="{Binding GroupedItems}"
VerticalOptions="FillAndExpand"
ItemTemplate="{StaticResource listItemDataTemplateSelector}"
IsGrouped="True"
SelectionMode="Single"
SelectionChanged="RowSelected"
StyleClass="list, list-platform">
<CollectionView.GroupHeaderTemplate>
<DataTemplate x:DataType="pages:GroupingsPageListGroup">
<StackLayout
Spacing="0" Padding="0" VerticalOptions="FillAndExpand"
StyleClass="list-row-header-container, list-row-header-container-platform">
<BoxView
StyleClass="list-section-separator-top, list-section-separator-top-platform" />
<StackLayout StyleClass="list-row-header, list-row-header-platform">
<Label
Text="{Binding Name}"
StyleClass="list-header, list-header-platform" />
<Label
Text="{Binding ItemCount}"
StyleClass="list-header-sub" />
</StackLayout>
</StackLayout>
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
</controls:ExtendedCollectionView>
StyleClass="list, list-platform" />
</StackLayout>
</ResourceDictionary>
</ContentPage.Resources>

View File

@@ -11,6 +11,7 @@ using Bit.Core.Utilities;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms;
namespace Bit.App.Pages
@@ -36,14 +37,14 @@ namespace Bit.App.Pages
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
_passwordRepromptService = ServiceContainer.Resolve<IPasswordRepromptService>("passwordRepromptService");
GroupedItems = new ExtendedObservableCollection<GroupingsPageListGroup>();
GroupedItems = new ObservableRangeCollection<IGroupingsPageListItem>();
CipherOptionsCommand = new Command<CipherView>(CipherOptionsAsync);
}
public string Name { get; set; }
public string Uri { get; set; }
public Command CipherOptionsCommand { get; set; }
public ExtendedObservableCollection<GroupingsPageListGroup> GroupedItems { get; set; }
public ObservableRangeCollection<IGroupingsPageListItem> GroupedItems { get; set; }
public bool ShowList
{
@@ -65,9 +66,9 @@ namespace Bit.App.Pages
public void Init(AppOptions appOptions)
{
_appOptions = appOptions;
Uri = appOptions.Uri;
Uri = appOptions?.Uri;
string name = null;
if (Uri.StartsWith(Constants.AndroidAppProtocol))
if (Uri?.StartsWith(Constants.AndroidAppProtocol) ?? false)
{
name = Uri.Substring(Constants.AndroidAppProtocol.Length);
}
@@ -105,7 +106,49 @@ namespace Bit.App.Pages
new GroupingsPageListGroup(fuzzy, AppResources.PossibleMatchingItems, fuzzy.Count, false,
!hasMatching));
}
GroupedItems.ResetWithRange(groupedItems);
// TODO: refactor this
if (Device.RuntimePlatform == Device.Android
||
GroupedItems.Any())
{
var items = new List<IGroupingsPageListItem>();
foreach (var itemGroup in groupedItems)
{
items.Add(new GroupingsPageHeaderListItem(itemGroup.Name, itemGroup.ItemCount));
items.AddRange(itemGroup);
}
GroupedItems.ReplaceRange(items);
}
else
{
// HACK: we need this on iOS, so that it doesn't crash when adding coming from an empty list
var first = true;
var items = new List<IGroupingsPageListItem>();
foreach (var itemGroup in groupedItems)
{
if (!first)
{
items.Add(new GroupingsPageHeaderListItem(itemGroup.Name, itemGroup.ItemCount));
}
else
{
first = false;
}
items.AddRange(itemGroup);
}
if (groupedItems.Any())
{
GroupedItems.ReplaceRange(new List<IGroupingsPageListItem> { new GroupingsPageHeaderListItem(groupedItems[0].Name, groupedItems[0].ItemCount) });
GroupedItems.AddRange(items);
}
else
{
GroupedItems.Clear();
}
}
ShowList = groupedItems.Any();
}

View File

@@ -55,30 +55,53 @@
<DataTemplate x:Key="groupTemplate"
x:DataType="pages:GroupingsPageListItem">
<controls:ExtendedStackLayout Orientation="Horizontal"
StyleClass="list-row, list-row-platform">
StyleClass="list-row, list-row-platform">
<controls:IconLabel Text="{Binding Icon, Mode=OneWay}"
HorizontalOptions="Start"
VerticalOptions="Center"
StyleClass="list-icon, list-icon-platform"
ShouldUpdateFontSizeDynamicallyForAccesibility="True">
HorizontalOptions="Start"
VerticalOptions="Center"
StyleClass="list-icon, list-icon-platform"
ShouldUpdateFontSizeDynamicallyForAccesibility="True">
<controls:IconLabel.Effects>
<effects:FixedSizeEffect />
</controls:IconLabel.Effects>
</controls:IconLabel>
<Label Text="{Binding Name, Mode=OneWay}"
LineBreakMode="TailTruncation"
HorizontalOptions="FillAndExpand"
VerticalOptions="CenterAndExpand"
StyleClass="list-title"/>
LineBreakMode="TailTruncation"
HorizontalOptions="FillAndExpand"
VerticalOptions="CenterAndExpand"
StyleClass="list-title"/>
<Label Text="{Binding ItemCount, Mode=OneWay}"
HorizontalOptions="End"
VerticalOptions="CenterAndExpand"
HorizontalTextAlignment="End"
StyleClass="list-sub"/>
HorizontalOptions="End"
VerticalOptions="CenterAndExpand"
HorizontalTextAlignment="End"
StyleClass="list-sub"/>
</controls:ExtendedStackLayout>
</DataTemplate>
<DataTemplate
x:Key="headerTemplate"
x:DataType="pages:GroupingsPageHeaderListItem">
<StackLayout
Spacing="0"
Padding="0"
VerticalOptions="FillAndExpand"
StyleClass="list-row-header-container, list-row-header-container-platform">
<BoxView
StyleClass="list-section-separator-top, list-section-separator-top-platform" />
<StackLayout StyleClass="list-row-header, list-row-header-platform">
<Label
Text="{Binding Title}"
StyleClass="list-header, list-header-platform" />
<Label
Text="{Binding ItemCount}"
StyleClass="list-header-sub" />
</StackLayout>
<BoxView StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform" />
</StackLayout>
</DataTemplate>
<pages:GroupingsPageListItemSelector x:Key="listItemDataTemplateSelector"
HeaderTemplate="{StaticResource headerTemplate}"
CipherTemplate="{StaticResource cipherTemplate}"
GroupTemplate="{StaticResource groupTemplate}" />
@@ -105,32 +128,9 @@
ItemsSource="{Binding GroupedItems}"
VerticalOptions="FillAndExpand"
ItemTemplate="{StaticResource listItemDataTemplateSelector}"
IsGrouped="True"
SelectionMode="Single"
SelectionChanged="RowSelected"
StyleClass="list, list-platform">
<CollectionView.GroupHeaderTemplate>
<DataTemplate x:DataType="pages:GroupingsPageListGroup">
<StackLayout
Spacing="0" Padding="0" VerticalOptions="FillAndExpand"
StyleClass="list-row-header-container, list-row-header-container-platform">
<BoxView
StyleClass="list-section-separator-top, list-section-separator-top-platform"
IsVisible="{Binding First, Converter={StaticResource inverseBool}}" />
<StackLayout StyleClass="list-row-header, list-row-header-platform">
<Label
Text="{Binding Name}"
StyleClass="list-header, list-header-platform" />
<Label
Text="{Binding ItemCount}"
StyleClass="list-header-sub" />
</StackLayout>
<BoxView StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform" />
</StackLayout>
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
</controls:ExtendedCollectionView>
StyleClass="list, list-platform" />
</RefreshView>
</StackLayout>
</ResourceDictionary>

View File

@@ -0,0 +1,14 @@
namespace Bit.App.Pages
{
public class GroupingsPageHeaderListItem : IGroupingsPageListItem
{
public GroupingsPageHeaderListItem(string title, string itemCount)
{
Title = title;
ItemCount = itemCount;
}
public string Title { get; }
public string ItemCount { get; set; }
}
}

View File

@@ -5,7 +5,7 @@ using Bit.Core.Models.View;
namespace Bit.App.Pages
{
public class GroupingsPageListItem
public class GroupingsPageListItem : IGroupingsPageListItem
{
private string _icon;
private string _name;

View File

@@ -4,11 +4,17 @@ namespace Bit.App.Pages
{
public class GroupingsPageListItemSelector : DataTemplateSelector
{
public DataTemplate HeaderTemplate { get; set; }
public DataTemplate CipherTemplate { get; set; }
public DataTemplate GroupTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
if (item is GroupingsPageHeaderListItem)
{
return HeaderTemplate;
}
if (item is GroupingsPageListItem listItem)
{
return listItem.Cipher != null ? CipherTemplate : GroupTemplate;

View File

@@ -11,6 +11,7 @@ using Bit.Core.Enums;
using Bit.Core.Models.Domain;
using Bit.Core.Models.View;
using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms;
namespace Bit.App.Pages
@@ -63,7 +64,7 @@ namespace Bit.App.Pages
Loading = true;
PageTitle = AppResources.MyVault;
GroupedItems = new ExtendedObservableCollection<GroupingsPageListGroup>();
GroupedItems = new ObservableRangeCollection<IGroupingsPageListItem>();
RefreshCommand = new Command(async () =>
{
Refreshing = true;
@@ -144,7 +145,7 @@ namespace Bit.App.Pages
public AccountSwitchingOverlayViewModel AccountSwitchingOverlayViewModel { get; }
public ExtendedObservableCollection<GroupingsPageListGroup> GroupedItems { get; set; }
public ObservableRangeCollection<IGroupingsPageListItem> GroupedItems { get; set; }
public Command RefreshCommand { get; set; }
public Command<CipherView> CipherOptionsCommand { get; set; }
public bool LoadedOnce { get; set; }
@@ -275,12 +276,54 @@ namespace Bit.App.Pages
{
new GroupingsPageListItem()
{
IsTrash = true,
IsTrash = true,
ItemCount = _deletedCount.ToString("N0")
}
}, AppResources.Trash, _deletedCount, uppercaseGroupNames, false));
}
GroupedItems.ResetWithRange(groupedItems);
// TODO: refactor this
if (Device.RuntimePlatform == Device.Android
||
GroupedItems.Any())
{
var items = new List<IGroupingsPageListItem>();
foreach (var itemGroup in groupedItems)
{
items.Add(new GroupingsPageHeaderListItem(itemGroup.Name, itemGroup.ItemCount));
items.AddRange(itemGroup);
}
GroupedItems.ReplaceRange(items);
}
else
{
// HACK: we need this on iOS, so that it doesn't crash when adding coming from an empty list
var first = true;
var items = new List<IGroupingsPageListItem>();
foreach (var itemGroup in groupedItems)
{
if (!first)
{
items.Add(new GroupingsPageHeaderListItem(itemGroup.Name, itemGroup.ItemCount));
}
else
{
first = false;
}
items.AddRange(itemGroup);
}
if (groupedItems.Any())
{
GroupedItems.ReplaceRange(new List<IGroupingsPageListItem> { new GroupingsPageHeaderListItem(groupedItems[0].Name, groupedItems[0].ItemCount) });
GroupedItems.AddRange(items);
}
else
{
GroupedItems.Clear();
}
}
}
finally
{

View File

@@ -0,0 +1,6 @@
namespace Bit.App.Pages
{
public interface IGroupingsPageListItem
{
}
}

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Skrap rekening</value>
</data>

View File

@@ -276,16 +276,16 @@
<value>Çıxış etmək istədiyinizə əminsiniz?</value>
</data>
<data name="RemoveAccount" xml:space="preserve">
<value>Remove Account</value>
<value>Hesabı sil</value>
</data>
<data name="RemoveAccountConfirmation" xml:space="preserve">
<value>Are you sure you want to remove this account?</value>
<value>Bu istifadəçini silmək istədiyinizə əminsiniz?</value>
</data>
<data name="AccountAlreadyAdded" xml:space="preserve">
<value>Account Already Added</value>
<value>Hesab artıq əlavə edildi</value>
</data>
<data name="SwitchToAlreadyAddedAccountConfirmation" xml:space="preserve">
<value>Would you like to switch to it now?</value>
<value>Buna indi keçmək istəyirsiniz?</value>
</data>
<data name="MasterPassword" xml:space="preserve">
<value>Ana parol</value>
@@ -2105,19 +2105,28 @@
<value>Bir və ya daha çox təşkilat siyasəti, fərdi anbarınızı ixrac etməyinizin qarşısını alır.</value>
</data>
<data name="AddAccount" xml:space="preserve">
<value>Add Account</value>
<value>Hesab əlavə et</value>
</data>
<data name="AccountUnlocked" xml:space="preserve">
<value>Unlocked</value>
<value>Kilidi açıldı</value>
</data>
<data name="AccountLocked" xml:space="preserve">
<value>Locked</value>
<value>Kilidli</value>
</data>
<data name="AccountLoggedOut" xml:space="preserve">
<value>Logged Out</value>
<value>Çıxış edildi</value>
</data>
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
<value>Növbəti mövcud hesaba keçildi</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Hesab kilidlidir</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Hesabdan uğurla çıxış edildi</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Hesab uğurla silindi</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Hesabı sil</value>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
</data>

View File

@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Превключено към следващата налична регистрация</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Регистрацията е заключена</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Отписването от регистрацията беше успешно</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Регистрацията беше премахната успешно</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Изтриване на регистрацията</value>
</data>

View File

@@ -1299,7 +1299,7 @@
<value>1. Go to the iOS "Settings" app</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Tap "Passwords &amp; Accounts"</value>
<value>2. Tap "Passwords"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Tap "AutoFill Passwords"</value>
@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
</data>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Prebačeni ste na sljedeći dostupan račun </value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Račun zaključan </value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Uspješno odjavljeni sa računa </value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Račun je uspješno uklonjen</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Obriši račun</value>
</data>

View File

@@ -276,16 +276,16 @@
<value>Segur que voleu tancar la sessió?</value>
</data>
<data name="RemoveAccount" xml:space="preserve">
<value>Remove Account</value>
<value>Suprimeix el compte</value>
</data>
<data name="RemoveAccountConfirmation" xml:space="preserve">
<value>Are you sure you want to remove this account?</value>
<value>Voleu suprimir el compte?</value>
</data>
<data name="AccountAlreadyAdded" xml:space="preserve">
<value>Account Already Added</value>
<value>El compte ja s'ha afegit</value>
</data>
<data name="SwitchToAlreadyAddedAccountConfirmation" xml:space="preserve">
<value>Would you like to switch to it now?</value>
<value>T'agradaria canviar-lo ara?</value>
</data>
<data name="MasterPassword" xml:space="preserve">
<value>Contrasenya mestra</value>
@@ -2105,19 +2105,28 @@
<value>Una o més polítiques d'organització us impedeixen exportar la vostra caixa forta.</value>
</data>
<data name="AddAccount" xml:space="preserve">
<value>Add Account</value>
<value>Afig compte</value>
</data>
<data name="AccountUnlocked" xml:space="preserve">
<value>Unlocked</value>
<value>Desbloquejat</value>
</data>
<data name="AccountLocked" xml:space="preserve">
<value>Locked</value>
<value>Bloquejat</value>
</data>
<data name="AccountLoggedOut" xml:space="preserve">
<value>Logged Out</value>
<value>Sessió tancada</value>
</data>
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
<value>S'ha canviat al següent compte disponible</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Compte bloquejat</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>El compte s'ha tancat correctament</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>El compte s'ha suprimit correctament</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Suprimeix el compte</value>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Přepnuto na další dostupný účet</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Odstranit účet</value>
</data>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Skiftede til næste tilgængelige konto</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Konto låst</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Konto logget ud</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Konto fjernet</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Slet konto</value>
</data>

View File

@@ -1299,7 +1299,7 @@
<value>1. Gehe in die iOS Einstellungen</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Drücke "Passwörter &amp; Accounts"</value>
<value>2. Tippe auf "Passwörter"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Tippe auf "Automatisch ausfüllen"</value>
@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Zum nächsten verfügbaren Konto gewechselt</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Konto gesperrt</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Konto erfolgreich abgemeldet</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Konto erfolgreich gelöscht</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Konto löschen</value>
</data>

View File

@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Μετάβαση στον επόμενο διαθέσιμο λογαριασμό</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Διαγραφή Λογαριασμού</value>
</data>

View File

@@ -2132,6 +2132,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
</data>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Cambiado a la siguiente cuenta disponible</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Eliminar cuenta</value>
</data>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Vahetati järgmise saadaoleva konto peale</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Kasutajakonto on lukus</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Konto on edukalt välja logitud</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Konto on edukalt eemaldatud</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Kustuta konto</value>
</data>

View File

@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>به حساب بعدی موجود تغییر کرد</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>حساب قفل شده است</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>حساب کاربری با موفقیت خارج شد</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>حساب کاربری با موفقیت حذف شد</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>حذف حساب</value>
</data>

View File

@@ -1299,7 +1299,7 @@
<value>1. Siirry iOS:n "Asetukset" -sovellukseen</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Napauta "Salasanat ja tilit"</value>
<value>2. Napauta "Salasanat"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Napauta "Täytä salasanat automaattisesti"</value>
@@ -1538,7 +1538,7 @@
<value>Oletus (järjestelmä)</value>
</data>
<data name="CopyNotes" xml:space="preserve">
<value>Kopioi muistiinpanot</value>
<value>Kopioi merkinnät</value>
</data>
<data name="Exit" xml:space="preserve">
<value>Poistu</value>
@@ -1569,7 +1569,7 @@
<value>Kun sovellus käynnistetään uudelleen</value>
</data>
<data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>Automaattinen täyttö tekee Bitwarden-holvisi käytöstä sivustoilla ja muissa sovelluksissa helppoa. Näyttää siltä, ettei automaattista täyttöä ole otettu käyttöön. Voit tehdä sen "Asetukset" -näytöstä.</value>
<value>Automaattinen täyttö tekee Bitwarden-holvisi käytöstä sivustoilla ja muissa sovelluksissa helppoa. Näyttää siltä, ettei automaattista täyttöä ole otettu käyttöön. Voit tehdä sen "Asetukset" -ruudusta.</value>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Teema vaihtuu kun sovellus käynnistetään uudelleen.</value>
@@ -1931,7 +1931,7 @@
<value>Salasana on poistettu.</value>
</data>
<data name="NotesInfo" xml:space="preserve">
<value>Yksityiset muistiinpanot tästä Sendistä.</value>
<value>Yksityisiä merkintöjä tästä Sendistä.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="DisableSend" xml:space="preserve">
@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Vaihdettu seuraavaan käytettävissä olevaan tiliin</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Tili lukittu</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Tilin uloskirjaus onnistui</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Tilin poisto onnistui</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Poista tili</value>
</data>

View File

@@ -1299,7 +1299,7 @@
<value>1. Go to the iOS "Settings" app</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Tap "Passwords &amp; Accounts"</value>
<value>2. Tap "Passwords"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Tap "AutoFill Passwords"</value>
@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
</data>

View File

@@ -1165,7 +1165,7 @@
<value>Le service de saisie automatique de Bitwarden utilise l'outil de saisie automatique d'Android pour aider à saisir les identifiants, les cartes de crédit et les informations d'identité dans d'autres applis sur votre appareil.</value>
</data>
<data name="BitwardenAutofillServiceDescription" xml:space="preserve">
<value>Utilisez le service d'accessibilité de Bitwarden pour la saisie automatique de vos identifiants.</value>
<value>Utilisez le service de remplissage automatique de Bitwarden pour remplir les informations de connexion dans d'autres applications.</value>
</data>
<data name="BitwardenAutofillServiceOpenAutofillSettings" xml:space="preserve">
<value>Ouvrir les paramètres de remplissage automatique</value>
@@ -1299,7 +1299,7 @@
<value>1. Allez dans l'application "Réglages" d'iOS</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Appuyez sur "Mots de passe et comptes"</value>
<value>2. Appuyez sur "Mots de passes et comptes"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Appuyez sur "Préremplir mots de passe"</value>
@@ -1935,7 +1935,7 @@
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="DisableSend" xml:space="preserve">
<value>Désactiver ce Send pour que personne ne puisse y accéder.</value>
<value>Désactiver cet envoi pour que personne ne puisse y accéder.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="NoSends" xml:space="preserve">
@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Passage au prochain compte disponible</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Compte verrouillé</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Compte déconnecté avec succès</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Compte supprimé avec succès</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Supprimer le compte</value>
</data>

View File

@@ -2126,6 +2126,15 @@ Bitwarden בעזרת פתיחת חלון "הגדרות".</value>
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
</data>

View File

@@ -1300,7 +1300,7 @@
<value>1. Go to the iOS "Settings" app</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Tap "Passwords &amp; Accounts"</value>
<value>2. Tap "Passwords"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Tap "AutoFill Passwords"</value>
@@ -2121,6 +2121,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
</data>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Obriši račun</value>
</data>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Megtörtént az átkapcsolás a következő elérhető fiókra.</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>A fiók lezárásra került.</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>A fiókból kijelentkezés sikeres volt.</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>A fiók eltávolítása sikeres volt.</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Fiók törlése</value>
</data>

View File

@@ -276,13 +276,13 @@
<value>Anda yakin ingin keluar?</value>
</data>
<data name="RemoveAccount" xml:space="preserve">
<value>Remove Account</value>
<value>Hapus Akun</value>
</data>
<data name="RemoveAccountConfirmation" xml:space="preserve">
<value>Are you sure you want to remove this account?</value>
<value>Apakah anda yakin ingin menghapus akun ini?</value>
</data>
<data name="AccountAlreadyAdded" xml:space="preserve">
<value>Account Already Added</value>
<value>Akun telah ditambahkan</value>
</data>
<data name="SwitchToAlreadyAddedAccountConfirmation" xml:space="preserve">
<value>Would you like to switch to it now?</value>
@@ -2105,22 +2105,31 @@
<value>One or more organization policies prevents your from exporting your personal vault.</value>
</data>
<data name="AddAccount" xml:space="preserve">
<value>Add Account</value>
<value>Tambahkan Akun</value>
</data>
<data name="AccountUnlocked" xml:space="preserve">
<value>Unlocked</value>
<value>Tidak terkunci</value>
</data>
<data name="AccountLocked" xml:space="preserve">
<value>Locked</value>
<value>Terkunci</value>
</data>
<data name="AccountLoggedOut" xml:space="preserve">
<value>Logged Out</value>
<value>Keluar</value>
</data>
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Akun terkunci</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Berhasil keluar</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
<value>Hapus akun</value>
</data>
<data name="DeletingYourAccountIsPermanent" xml:space="preserve">
<value>Deleting your account is permanent</value>
@@ -2129,13 +2138,13 @@
<value>Your account and all associated data will be erased and unrecoverable. Are you sure you want to continue?</value>
</data>
<data name="DeletingYourAccount" xml:space="preserve">
<value>Deleting your account</value>
<value>Hapus akun anda</value>
</data>
<data name="YourAccountHasBeenPermanentlyDeleted" xml:space="preserve">
<value>Your account has been permanently deleted</value>
<value>Akun Anda telah dihapus secara permanen.</value>
</data>
<data name="InvalidVerificationCode" xml:space="preserve">
<value>Invalid Verification Code.</value>
<value>Kode verifikasi tidak valid.</value>
</data>
<data name="RequestOTP" xml:space="preserve">
<value>Request one-time password</value>
@@ -2153,18 +2162,18 @@
<value>Sending code</value>
</data>
<data name="Verifying" xml:space="preserve">
<value>Verifying</value>
<value>Memverifikasi...</value>
</data>
<data name="ResendCode" xml:space="preserve">
<value>Resend Code</value>
<value>Kirim ulang kode</value>
</data>
<data name="AVerificationCodeWasSentToYourEmail" xml:space="preserve">
<value>A verification code was sent to your email</value>
<value>Kode verifikasi telah dikirim ke email Anda.</value>
</data>
<data name="AnErrorOccurredWhileSendingAVerificationCodeToYourEmailPleaseTryAgain" xml:space="preserve">
<value>An error occurred while sending a verification code to your email. Please try again</value>
</data>
<data name="EnterTheVerificationCodeThatWasSentToYourEmail" xml:space="preserve">
<value>Enter the verification code that was sent to your email</value>
<value>Masukkan kode verifikasi yang dikirim ke email anda</value>
</data>
</root>

View File

@@ -196,7 +196,7 @@
<value>Inviaci un'email per ottenere aiuto o fare una segnalazione.</value>
</data>
<data name="EnterPIN" xml:space="preserve">
<value>Inserisci il tuo PIN.</value>
<value>Digita il tuo PIN.</value>
</data>
<data name="Favorites" xml:space="preserve">
<value>Preferiti</value>
@@ -247,7 +247,7 @@
<comment>Description message for the alert when internet connection is required to continue.</comment>
</data>
<data name="InternetConnectionRequiredTitle" xml:space="preserve">
<value>Connessione ad Internet richiesta</value>
<value>Connessione a Internet richiesta</value>
<comment>Title for the alert when internet connection is required to continue.</comment>
</data>
<data name="InvalidMasterPassword" xml:space="preserve">
@@ -378,7 +378,7 @@
<value>Verifica impronta</value>
</data>
<data name="VerifyMasterPassword" xml:space="preserve">
<value>Verifica Password Principale</value>
<value>Verifica password principale</value>
</data>
<data name="VerifyPIN" xml:space="preserve">
<value>Verifica PIN</value>
@@ -393,7 +393,7 @@
<value>Visita il nostro sito</value>
</data>
<data name="VisitOurWebsiteDescription" xml:space="preserve">
<value>Visita il nostro sito per ottenere aiuto, notizie, mandarci una email e/o imparare di più su come usare Bitwarden.</value>
<value>Visita il nostro sito per ottenere aiuto, notizie, mandarci un'email e/o imparare di più su come usare Bitwarden.</value>
</data>
<data name="Website" xml:space="preserve">
<value>Sito web</value>
@@ -430,7 +430,7 @@
<value>Il modo più semplice per aggiungere nuovi login alla tua cassaforte è dall'estensione dell'applicazione Bitwarden. Scopri di più sull'utilizzo dell'estensione dell'applicazione Bitwarden navigando nella schermata "Impostazioni".</value>
</data>
<data name="BitwardenAppExtensionDescription" xml:space="preserve">
<value>Usa Bitwarden su Safari e altre app per auto-completare i tuoi login.</value>
<value>Usa Bitwarden su Safari e altre applicazioni per auto-completare i tuoi login.</value>
</data>
<data name="BitwardenAutofillService" xml:space="preserve">
<value>Servizio auto-completamento di Bitwarden</value>
@@ -448,7 +448,7 @@
<value>Cambia password principale</value>
</data>
<data name="ChangePasswordConfirmation" xml:space="preserve">
<value>Puoi cambiare la tua password principale solo sulla cassaforte online di bitwarden.com. Vuoi visitare ora il sito?</value>
<value>Puoi cambiare la tua password principale solo sulla cassaforte in linea di bitwarden.com. Vuoi visitare ora il sito?</value>
</data>
<data name="Close" xml:space="preserve">
<value>Chiudi</value>
@@ -467,7 +467,7 @@
<value>Modifica elemento</value>
</data>
<data name="EnableAutomaticSyncing" xml:space="preserve">
<value>Abilita la sincronizzazione automatica</value>
<value>Abilita sincronizzazione automatica</value>
</data>
<data name="EnterEmailForHint" xml:space="preserve">
<value>Inserisci l'indirizzo email del tuo account per ricevere il suggerimento della password principale.</value>
@@ -479,7 +479,7 @@
<value>Quasi fatto!</value>
</data>
<data name="ExtensionEnable" xml:space="preserve">
<value>Abilita l'Estensione App</value>
<value>Abilita l'estensione dell'applicazione</value>
</data>
<data name="ExtensionInSafari" xml:space="preserve">
<value>Su Safari, trova Bitwarden utilizzando l'icona di condivisione (suggerimento: scorri a destra sulla riga inferiore del menu).</value>
@@ -489,7 +489,7 @@
<value>Ottieni accesso immediato alle tue password!</value>
</data>
<data name="ExtensionReady" xml:space="preserve">
<value>Sei pronto a fare il login!</value>
<value>Sei pronto ad accedere!</value>
</data>
<data name="ExtensionSetup" xml:space="preserve">
<value>I tuoi login sono ora facilmente accessibili da Safari, Chrome e altre applicazioni supportate.</value>
@@ -510,10 +510,10 @@
<value>Impronta</value>
</data>
<data name="GeneratePassword" xml:space="preserve">
<value>Genera Password</value>
<value>Genera password</value>
</data>
<data name="GetPasswordHint" xml:space="preserve">
<value>Ottenere il suggerimento per la password principale</value>
<value>Ottieni il suggerimento per la password principale</value>
</data>
<data name="ImportItems" xml:space="preserve">
<value>Importa elementi</value>
@@ -555,7 +555,7 @@
<value>Azione timeout cassaforte</value>
</data>
<data name="VaultTimeoutLogOutConfirmation" xml:space="preserve">
<value>La disconnessione rimuove tutti gli accessi alla tua cassaforte e richiede l'autenticazione online dopo il periodo di scadenza. Sei sicuro di voler utilizzare questa impostazione?</value>
<value>La disconnessione rimuove tutti gli accessi alla tua cassaforte e richiede l'autenticazione in linea dopo il periodo di scadenza. Sei sicuro di voler utilizzare questa impostazione?</value>
</data>
<data name="LoggingIn" xml:space="preserve">
<value>Connessione in corso...</value>
@@ -574,10 +574,10 @@
<value>La password principale è la password che utilizzi per accedere alla tua cassaforte. È molto importante che tu non la dimentichi. Non c'è modo di recuperare questa password nel caso che tu la dimenticassi.</value>
</data>
<data name="MasterPasswordHint" xml:space="preserve">
<value>Indizio per la Password Principale (opzionale)</value>
<value>Suggerimento per la password principale (facoltativo)</value>
</data>
<data name="MasterPasswordHintDescription" xml:space="preserve">
<value>Un indizio per la password principale può aiutarti a ricordarla nel caso te la dimenticassi.</value>
<value>Un suggerimento per la password principale può aiutarti a ricordarla nel caso la dimenticassi.</value>
</data>
<data name="MasterPasswordLengthValMessage" xml:space="preserve">
<value>La password principale deve essere lunga almeno 8 caratteri.</value>
@@ -594,7 +594,7 @@
<value>Altre impostazioni</value>
</data>
<data name="MustLogInMainApp" xml:space="preserve">
<value>È necessario accedere all'app di Bitwarden principale prima di poter utilizzare l'estensione.</value>
<value>È necessario accedere all'applicazione principale di Bitwarden prima di poter utilizzare l'estensione.</value>
</data>
<data name="Never" xml:space="preserve">
<value>Mai</value>
@@ -619,7 +619,7 @@
<comment>Confirmation, like "Ok, I understand it"</comment>
</data>
<data name="OptionDefaults" xml:space="preserve">
<value>Le opzioni predefinite sono impostate dal generatore di password dell'app principale Bitwarden.</value>
<value>Le opzioni predefinite sono impostate dal generatore di password dell'applicazione principale Bitwarden.</value>
</data>
<data name="Options" xml:space="preserve">
<value>Opzioni</value>
@@ -631,7 +631,7 @@
<value>Password generata.</value>
</data>
<data name="PasswordGenerator" xml:space="preserve">
<value>Generatore di Password</value>
<value>Generatore di password</value>
</data>
<data name="PasswordHint" xml:space="preserve">
<value>Suggerimento password</value>
@@ -656,7 +656,7 @@
<value>Rigenera password</value>
</data>
<data name="RetypeMasterPassword" xml:space="preserve">
<value>Ri-digita la tua password principale</value>
<value>Ri-digita la password principale</value>
</data>
<data name="SearchVault" xml:space="preserve">
<value>Cerca nella cassaforte</value>
@@ -671,7 +671,7 @@
<value>Imposta PIN</value>
</data>
<data name="SetPINDirection" xml:space="preserve">
<value>Immetti un codice PIN a 4 cifre per sbloccare l'applicazione.</value>
<value>Digita un codice PIN a 4 cifre per sbloccare l'applicazione.</value>
</data>
<data name="ItemInformation" xml:space="preserve">
<value>Informazioni elemento</value>
@@ -704,7 +704,7 @@
<value>Verifica in due passaggi</value>
</data>
<data name="TwoStepLoginConfirmation" xml:space="preserve">
<value>L'autenticazione in due passaggi rende il tuo account più sicuro, richiedendo di verificare l'accesso con un altro dispositivo come una chiave di sicurezza, app di autenticazione, SMS, telefonata o email. Può essere abilitata su bitwarden.com. Vuoi visitare il sito ora?</value>
<value>L'autenticazione in due passaggi rende il tuo account più sicuro, richiedendo di verificare l'accesso con un altro dispositivo come una chiave di sicurezza, applicazione di autenticazione, SMS, telefonata o email. Può essere abilitata su bitwarden.com. Vuoi visitare il sito ora?</value>
</data>
<data name="UnlockWith" xml:space="preserve">
<value>Sblocca con {0}</value>
@@ -759,7 +759,7 @@
<value>Apri impostazioni di accessibilità</value>
</data>
<data name="BitwardenAutofillServiceStep1" xml:space="preserve">
<value>1. Nella schermata impostazioni di accessibilità di Android, tocca "Bitwarden".</value>
<value>1. Nella schermata impostazioni di accessibilità di Android, tocca "Bitwarden" nella gestione dei servizi.</value>
</data>
<data name="BitwardenAutofillServiceStep2" xml:space="preserve">
<value>2. Attiva l'interruttore e premi OK per accettare.</value>
@@ -1597,7 +1597,7 @@
<value>Verifica biometrica</value>
</data>
<data name="Biometrics" xml:space="preserve">
<value>Dati biometrici</value>
<value>dati biometrici</value>
</data>
<data name="UseBiometricsToUnlock" xml:space="preserve">
<value>Sblocca con dati biometrici</value>
@@ -1665,7 +1665,7 @@
<comment>Clone an entity (verb).</comment>
</data>
<data name="PasswordGeneratorPolicyInEffect" xml:space="preserve">
<value>Una o più policy dell'organizzazione controllano le impostazioni del tuo generatore</value>
<value>Una o più politiche dell'organizzazione stanno influenzando le impostazioni del tuo generatore</value>
</data>
<data name="Open" xml:space="preserve">
<value>Apri</value>
@@ -1926,7 +1926,7 @@
<value>Sei sicuro di voler rimuovere la password?</value>
</data>
<data name="RemovingSendPassword" xml:space="preserve">
<value>Rimuovo la password</value>
<value>Rimozione password</value>
</data>
<data name="SendPasswordRemoved" xml:space="preserve">
<value>La password è stata rimossa.</value>
@@ -2052,10 +2052,10 @@
<value>Aggiorna password principale</value>
</data>
<data name="UpdateMasterPasswordWarning" xml:space="preserve">
<value>La tua password principale è stata recentemente modificata da un amministratore nella tua organizzazione. Per accedere alla cassaforte, devi aggiornarla ora. Procedendo sarai disconnesso dalla sessione attuale, richiedendo di effettuare nuovamente l'accesso. Le sessioni attive su altri dispositivi possono continuare a rimanere attive per un massimo di un'ora.</value>
<value>La tua password principale è stata recentemente modificata da un amministratore nella tua organizzazione. Per accedere alla cassaforte, aggiorna ora la password principale. Procedendo sarai disconnesso dalla sessione attuale e ti sarà richiesto di effettuare nuovamente l'accesso. Le sessioni attive su altri dispositivi potrebbero continuare a rimanere attive per un massimo di un'ora.</value>
</data>
<data name="UpdatingPassword" xml:space="preserve">
<value>Aggiornamento password in corso</value>
<value>Aggiornamento password</value>
</data>
<data name="UpdatePasswordError" xml:space="preserve">
<value>Attualmente non è possibile aggiornare la password</value>
@@ -2094,7 +2094,7 @@
<value>Assicurati che il browser predefinito supporti WebAuthn e riprova.</value>
</data>
<data name="ResetPasswordAutoEnrollInviteWarning" xml:space="preserve">
<value>Questa organizzazione ha una policy aziendale che ti iscriverà automaticamente al ripristino della password. Ciò permetterà agli amministratori dell'organizzazione di cambiare la tua password principale.</value>
<value>Questa organizzazione ha una politica aziendale che ti iscriverà automaticamente al ripristino della password. Ciò permetterà agli amministratori dell'organizzazione di cambiare la tua password principale.</value>
</data>
<data name="VaultTimeoutPolicyInEffect" xml:space="preserve">
<value>Le policy dell'organizzazione controllano il timeout della tua cassaforte. Il tempo massimo consentito è di $HOURS$ ore e $MINUTES$ minuti</value>
@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Passato all'account successivo disponibile</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account bloccato</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account disconnesso correttamente</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account rimosso correttamente</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Elimina account</value>
</data>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>次の利用可能なアカウントに切り替えました</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>アカウントをロックしました</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>ログアウトしました</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>アカウントを削除しました</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>アカウントの削除</value>
</data>

View File

@@ -1299,7 +1299,7 @@
<value>1. Go to the iOS "Settings" app</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Tap "Passwords &amp; Accounts"</value>
<value>2. Tap "Passwords"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Tap "AutoFill Passwords"</value>
@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
</data>

View File

@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
</data>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>사용 가능한 다음 계정으로 전환함</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>계정 삭제</value>
</data>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Pārslēdzās uz nākamo pieejamo kontu</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Konts ir slēgts</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Izrakstīšanās no konta bija veiksmīga</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Konts tika veiksmīgi noņemts</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Dzēst kontu</value>
</data>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
</data>

View File

@@ -276,13 +276,13 @@
<value>Er du sikker på at du vil logge av?</value>
</data>
<data name="RemoveAccount" xml:space="preserve">
<value>Remove Account</value>
<value>Fjern konto</value>
</data>
<data name="RemoveAccountConfirmation" xml:space="preserve">
<value>Are you sure you want to remove this account?</value>
<value>Er du sikker på at du vil fjerne denne kontoen?</value>
</data>
<data name="AccountAlreadyAdded" xml:space="preserve">
<value>Account Already Added</value>
<value>Kontoen er allerede lagt til</value>
</data>
<data name="SwitchToAlreadyAddedAccountConfirmation" xml:space="preserve">
<value>Would you like to switch to it now?</value>
@@ -549,13 +549,13 @@
<value>Umiddelbart</value>
</data>
<data name="VaultTimeout" xml:space="preserve">
<value>Tidsavbrudd i hvelvet</value>
<value>Tidsavbrudd for hvelvet</value>
</data>
<data name="VaultTimeoutAction" xml:space="preserve">
<value>Handling ved pause i hvelvet</value>
<value>Hendelse ved tidsavbrudd for hvelvet</value>
</data>
<data name="VaultTimeoutLogOutConfirmation" xml:space="preserve">
<value>Hvis du logger ut, fjerner du all tilgang til hvelvet ditt og krever online godkjenning etter tidsavbrudd. Er du sikker på at du vil bruke denne innstillingen?</value>
<value>Dersom du logger ut vil all tilgang til hvelvet fjernes og du må autentisere online etter tidsavbruddet. Er du sikker på at du vil bruke denne innstillingen?</value>
</data>
<data name="LoggingIn" xml:space="preserve">
<value>Logger på...</value>
@@ -750,7 +750,7 @@
<comment>This is used for the autofill service. ex. "There are no items in your vault for twitter.com".</comment>
</data>
<data name="BitwardenAutofillServiceOverlay" xml:space="preserve">
<value>Når du velger et inntastingsfelt og ser Bitwardens tjeneste for automatiske utfylling, kan du trykke på den for å starte den automatisk utfyllingen.</value>
<value>Når du velger et inntastingsfelt og ser Bitwardens autofylltjeneste, kan du trykke på den for å starte autofylltjenesten.</value>
</data>
<data name="BitwardenAutofillServiceNotificationContent" xml:space="preserve">
<value>Trykk på denne beskjeden for å auto-utfylle en gjenstand fra ditt hvelv.</value>
@@ -774,7 +774,7 @@
<value>Status</value>
</data>
<data name="BitwardenAutofillServiceAlert2" xml:space="preserve">
<value>Den enkleste måten å legge til nye innlogginger i hvelvet ditt, er fra Bitwarden sin auto-utfyllingstjeneste. Lær mer om å bruke Bitwarden sin auto-utfyllingstjeneste ved å navigere til "Innstillinger".</value>
<value>Den enkleste måten å legge til nye innlogginger i hvelvet ditt, er fra Bitwarden sin autofylltjeneste. Lær mer om å bruke Bitwarden sin autofylltjeneste ved å navigere til "Innstillinger".</value>
</data>
<data name="Autofill" xml:space="preserve">
<value>Auto-utfylling</value>
@@ -1156,16 +1156,16 @@
<value>Det er ingen gjenstander i denne mappen.</value>
</data>
<data name="NoItemsTrash" xml:space="preserve">
<value>Det er ingen objekter i papirkurven.</value>
<value>Det er ingen elementer i papirkurven.</value>
</data>
<data name="AutofillAccessibilityService" xml:space="preserve">
<value>Auto-utfyllingstilgjengelighetstjeneste</value>
</data>
<data name="AutofillServiceDescription" xml:space="preserve">
<value>Bitwarden sin auto-utfyllingstjeneste bruker Android Autofill Framework for å bidra til å fylle inn innlogginger, bankkort og identifikasjonsinfo inn i andre apper på din enhet.</value>
<value>Bitwarden sin autofylltjeneste bruker Android Autofill Framework for å bidra til å fylle inn innlogginger, bankkort og identifikasjonsinfo inn i andre apper på din enhet.</value>
</data>
<data name="BitwardenAutofillServiceDescription" xml:space="preserve">
<value>Bruk Bitwarden sin auto-utfyllingstjeneste for å fylle ut innlogginger, bankkort og identifikasjonsinfo i andre apper.</value>
<value>Bruk Bitwarden sin autofylltjeneste for å fylle ut innlogginger, bankkort og identifikasjonsinfo i andre apper.</value>
</data>
<data name="BitwardenAutofillServiceOpenAutofillSettings" xml:space="preserve">
<value>Åpne auto-utfyllingsinnstillingene</value>
@@ -1199,7 +1199,7 @@
<value>Skjult</value>
</data>
<data name="FieldTypeLinked" xml:space="preserve">
<value>Tilknyttet</value>
<value>Linket</value>
</data>
<data name="FieldTypeText" xml:space="preserve">
<value>Tekst</value>
@@ -1299,7 +1299,7 @@
<value>1. Gå til iOS-appen «Innstillinger»</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Trykk på «Passord og kontoer»</value>
<value>2. Trykk på "Passord og kontoer"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Trykk «Autoutfyll passord»</value>
@@ -1329,10 +1329,10 @@
<value>Innlogginger</value>
</data>
<data name="SecureNotes" xml:space="preserve">
<value>Sikre notiser</value>
<value>Sikre notater</value>
</data>
<data name="AllItems" xml:space="preserve">
<value>Alle gjenstander</value>
<value>Alle elementer</value>
</data>
<data name="URIs" xml:space="preserve">
<value>URI-er</value>
@@ -1343,13 +1343,13 @@
<comment>A loading message when doing an exposed password check.</comment>
</data>
<data name="CheckPassword" xml:space="preserve">
<value>Sjekk om passordet har blitt utsatt.</value>
<value>Sjekk om passordet har blitt lekket.</value>
</data>
<data name="PasswordExposed" xml:space="preserve">
<value>Dette passordet har blitt utsatt {0} gang(er) i et databrudd. Du burde endre det.</value>
<value>Dette passordet har blitt eksponert {0} gang(er) i et datalekkasjer. Du bør endre det.</value>
</data>
<data name="PasswordSafe" xml:space="preserve">
<value>Dette passordet ble ikke funnet i noen kjente databrudd. Det burde være trygt å bruke.</value>
<value>Dette passordet ble ikke funnet i noen kjente datalekkasjer. Det bør være trygt å bruke.</value>
</data>
<data name="IdentityName" xml:space="preserve">
<value>Identitetsnavn</value>
@@ -1364,10 +1364,10 @@
<value>Typer</value>
</data>
<data name="NoPasswordsToList" xml:space="preserve">
<value>Det er ingen passord å liste opp.</value>
<value>Det er ingen passord å vise</value>
</data>
<data name="NoItemsToList" xml:space="preserve">
<value>Det er ingen gjenstander å liste opp.</value>
<value>Det er ingen elementer å vise.</value>
</data>
<data name="SearchCollection" xml:space="preserve">
<value>Søk i samling</value>
@@ -1388,13 +1388,13 @@
<value>Flytt opp</value>
</data>
<data name="Miscellaneous" xml:space="preserve">
<value>Annet</value>
<value>Diverse</value>
</data>
<data name="Ownership" xml:space="preserve">
<value>Eierskap</value>
</data>
<data name="WhoOwnsThisItem" xml:space="preserve">
<value>Hvem eier dette objektet?</value>
<value>Hvem eier dette elementet?</value>
</data>
<data name="NoCollectionsToList" xml:space="preserve">
<value>Det er ingen samlinger å liste opp.</value>
@@ -1404,7 +1404,7 @@
<comment>ex: Item moved to Organization.</comment>
</data>
<data name="ItemShared" xml:space="preserve">
<value>Gjenstanden har blitt delt.</value>
<value>Elementet har blitt delt.</value>
</data>
<data name="SelectOneCollection" xml:space="preserve">
<value>Du må velge minst én samling.</value>
@@ -1413,13 +1413,13 @@
<value>Del</value>
</data>
<data name="ShareItem" xml:space="preserve">
<value>Del objekt</value>
<value>Del element</value>
</data>
<data name="MoveToOrganization" xml:space="preserve">
<value>Flytt til organisasjon</value>
</data>
<data name="NoOrgsToList" xml:space="preserve">
<value>Det er ingen organisasjoner å liste opp.</value>
<value>Det er ingen organisasjoner å vise.</value>
</data>
<data name="MoveToOrgDesc" xml:space="preserve">
<value>Velg en organisasjon som du ønsker å flytte denne gjenstanden til. Flytting til en organisasjon overfører eierskap til den aktuelle organisasjonen. Du vil ikke lenger være den direkte eieren av denne varen når den er flyttet.</value>
@@ -1431,7 +1431,7 @@
<value>Passfrase</value>
</data>
<data name="WordSeparator" xml:space="preserve">
<value>Ordadskiller</value>
<value>Orddeler</value>
</data>
<data name="Clear" xml:space="preserve">
<value>Tøm</value>
@@ -1442,7 +1442,7 @@
<comment>Short for "Password Generator"</comment>
</data>
<data name="NoFoldersToList" xml:space="preserve">
<value>Det er ingen mapper å liste opp.</value>
<value>Det er ingen mapper å vise</value>
</data>
<data name="FingerprintPhrase" xml:space="preserve">
<value>Fingeravtrykksfrase</value>
@@ -1474,10 +1474,10 @@
<value>30 minutter</value>
</data>
<data name="SetPINDescription" xml:space="preserve">
<value>Angi PIN-koden din for å låse opp Bitwarden. PIN-innstillingene tilbakestilles hvis du logger deg helt ut av programmet.</value>
<value>Angi PIN-koden for å låse opp Bitwarden. PIN-innstillingene dine blir tilbakestilt hvis du noen gang logger deg ut av applikasjonen.</value>
</data>
<data name="LoggedInAsOn" xml:space="preserve">
<value>Logget på som {0} gjennom {1}.</value>
<value>Logget på som {0} {1}.</value>
<comment>ex: Logged in as user@example.com on bitwarden.com.</comment>
</data>
<data name="VaultLockedMasterPassword" xml:space="preserve">
@@ -1494,7 +1494,7 @@
<comment>A dark color</comment>
</data>
<data name="Light" xml:space="preserve">
<value>Lyst</value>
<value>Lys</value>
<comment>A light color</comment>
</data>
<data name="FiveMinutes" xml:space="preserve">
@@ -1517,7 +1517,7 @@
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
</data>
<data name="ClearClipboardDescription" xml:space="preserve">
<value>Slett automatisk kopierte verdier fra utklippstavlen.</value>
<value>Slett kopierte verdier fra utklippstavlen automatisk.</value>
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
</data>
<data name="DefaultUriMatchDetection" xml:space="preserve">
@@ -1544,10 +1544,10 @@
<value>Avslutt</value>
</data>
<data name="ExitConfirmation" xml:space="preserve">
<value>Er du sikker på at du vil lukke Bitwarden?</value>
<value>Er du sikker på at du vil avslutte Bitwarden?</value>
</data>
<data name="PINRequireMasterPasswordRestart" xml:space="preserve">
<value>You you want to require unlocking with your master password when the application is restarted?</value>
<value>Ønsker du å låse opp ved å bruke hovedpassordet når applikasjonen startes på nytt?</value>
</data>
<data name="Black" xml:space="preserve">
<value>Svart</value>
@@ -1557,13 +1557,13 @@
<value>Svartelistede URI-er</value>
</data>
<data name="BlacklistedUrisDescription" xml:space="preserve">
<value>URIs that are blacklisted will not offer auto-fill. The list of apps should be comma separated. Ex: "https://twitter.com, androidapp://com.twitter.android".</value>
<value>URI-er som er svartelistet vil ikke bli fylt ut automatisk. Listen over apper bør kommasepareres. F.eks.: "https://twitter.com, androidapp://com.twitter.android".</value>
</data>
<data name="DisableSavePrompt" xml:space="preserve">
<value>Skru av lagreforespørsel</value>
<value>Deaktiver lagreforespørsel</value>
</data>
<data name="DisableSavePromptDescription" xml:space="preserve">
<value>"Lagreforespørselen" spør deg automatisk om du vil lagre nye objekter i hvelvet ditt når du skriver dem inn for første gang.</value>
<value>"Lagreforespørselen" spør deg automatisk om du vil lagre nye elementer i hvelvet ditt når du skriver dem inn for første gang.</value>
</data>
<data name="OnRestart" xml:space="preserve">
<value>Ved omstart av appen</value>
@@ -1579,7 +1579,7 @@
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Inkluder nummer</value>
<value>Inkluder siffer</value>
</data>
<data name="Download" xml:space="preserve">
<value>Last ned</value>
@@ -1588,13 +1588,13 @@
<value>Delt</value>
</data>
<data name="ToggleVisibility" xml:space="preserve">
<value>Toggle Visiblity</value>
<value>Filsynlighet av/på</value>
</data>
<data name="LoginExpired" xml:space="preserve">
<value>Innloggingsøkten din har utløpt.</value>
<value>Økten din har utløpt.</value>
</data>
<data name="BiometricsDirection" xml:space="preserve">
<value>Bruk biometri for å bekrefte.</value>
<value>Biometrisk verifisering</value>
</data>
<data name="Biometrics" xml:space="preserve">
<value>Biometri</value>
@@ -1627,7 +1627,7 @@
<value>Filformat</value>
</data>
<data name="ExportVaultMasterPasswordDescription" xml:space="preserve">
<value>Skriv inn ditt superpassordet for å eksportere dine hvelvdataer.</value>
<value>Skriv inn hovedpassordet for å eksportere hvelvdataene.</value>
</data>
<data name="SendVerificationCodeToEmail" xml:space="preserve">
<value>Send en verifiseringskode til e-posten din</value>
@@ -1639,13 +1639,13 @@
<value>Bekreft din identitet for å fortsette.</value>
</data>
<data name="ExportVaultWarning" xml:space="preserve">
<value>Denne eksporten inneholder hvelvdataene dine i et ukryptert format. Du skal ikke lagre eller sende den eksporterte filen over usikre kanaler (for eksempel e-post). Slett den umiddelbart etter at du er ferdig med å bruke den.</value>
<value>Denne eksporten inneholder hvelvdataene dine i et ukryptert format. Du bør ikke lagre eller sende den eksporterte filen over usikre kanaler (for eksempel e-post). Slett den umiddelbart etter at du er ferdig med å bruke den.</value>
</data>
<data name="EncExportKeyWarning" xml:space="preserve">
<value>Denne eksporten krypterer dataene dine ved hjelp av kontoen din sin krypteringsnøkkel. Hvis du noen gang endrer krypteringsnøkkelen til kontoen din, bør du eksportere dataene igjen, ettersom du da ikke vil kunne dekryptere denne eksportfilen.</value>
</data>
<data name="EncExportAccountWarning" xml:space="preserve">
<value>Kontokrypteringsnøkler er unike for hver Bitwarden sin brukerkonto, og du kan ikke importere en kryptert eksport til en annen konto.</value>
<value>Kontokrypteringsnøkler er unike for hver Bitwarden sin brukerkonto, du kan ikke importere en kryptert eksport til en annen konto.</value>
</data>
<data name="ExportVaultConfirmationTitle" xml:space="preserve">
<value>Bekreft eksport av hvelvet</value>
@@ -1688,7 +1688,7 @@
<comment>Message shown when interacting with the server</comment>
</data>
<data name="ItemSoftDeleted" xml:space="preserve">
<value>Varen ble sendt til papirkurven.</value>
<value>Elementet ble sendt til papirkurven.</value>
<comment>Confirmation message after successfully soft-deleting a login</comment>
</data>
<data name="Restore" xml:space="preserve">
@@ -1700,7 +1700,7 @@
<comment>Message shown when interacting with the server</comment>
</data>
<data name="ItemRestored" xml:space="preserve">
<value>Varen har blitt gjenopprettet.</value>
<value>Elementet har blitt gjenopprettet.</value>
<comment>Confirmation message after successfully restoring a soft-deleted item</comment>
</data>
<data name="Trash" xml:space="preserve">
@@ -1716,7 +1716,7 @@
<comment>Confirmation alert message when permanently deleteing a cipher.</comment>
</data>
<data name="DoYouReallyWantToRestoreCipher" xml:space="preserve">
<value>Vil du virkelig gjenopprette denne gjenstanden?</value>
<value>Vil du virkelig gjenopprette dette elementet?</value>
<comment>Confirmation alert message when restoring a soft-deleted cipher.</comment>
</data>
<data name="DoYouReallyWantToSoftDeleteCipher" xml:space="preserve">
@@ -1751,7 +1751,7 @@
<value>Angi hovedpassord</value>
</data>
<data name="SetMasterPasswordSummary" xml:space="preserve">
<value>For å fullføre innloggingen med SSO, angi et superpassord for å få tilgang til og beskytte hvelvet ditt.</value>
<value>For å fullføre innloggingen med SSO, angi et hovedpassord for å få tilgang til og beskytte hvelvet ditt.</value>
</data>
<data name="MasterPasswordPolicyInEffect" xml:space="preserve">
<value>En eller flere av organisasjonens vilkår krever hovedpassordet ditt for å oppfylle følgende krav:</value>
@@ -1763,13 +1763,13 @@
<value>Minste lengde på {0}</value>
</data>
<data name="PolicyInEffectUppercase" xml:space="preserve">
<value>Inneholder ett eller flere store tegn</value>
<value>Inneholder én eller flere store bokstaver</value>
</data>
<data name="PolicyInEffectLowercase" xml:space="preserve">
<value>Inneholder ett eller flere små tegn</value>
<value>Inneholder én eller flere små bokstaver</value>
</data>
<data name="PolicyInEffectNumbers" xml:space="preserve">
<value>Inneholde ett eller flere tall</value>
<value>Inneholde ett eller flere siffer</value>
</data>
<data name="PolicyInEffectSpecial" xml:space="preserve">
<value>Inneholder ett eller flere av de følgende spesialtegn: {0}</value>
@@ -1778,7 +1778,7 @@
<value>Ugyldig passord</value>
</data>
<data name="MasterPasswordPolicyValidationMessage" xml:space="preserve">
<value>Passordet oppfyller ikke organisasjonens krav. Kontroller policyinformasjonen og prøv på nytt.</value>
<value>Passordet oppfyller ikke organisasjonens krav. Kontroller organisasjonens vilkår og prøv på nytt.</value>
</data>
<data name="Loading" xml:space="preserve">
<value>Laster</value>
@@ -1788,13 +1788,13 @@
</value>
</data>
<data name="AcceptPoliciesError" xml:space="preserve">
<value>Bruksvilkårene og personvernerklæring er ikke godkjent.</value>
<value>Vilkårene for bruk og personvernerklæring er ikke akseptert.</value>
</data>
<data name="TermsOfService" xml:space="preserve">
<value>Vilkår for bruk</value>
</data>
<data name="PrivacyPolicy" xml:space="preserve">
<value>Retningslinjer for personvern</value>
<value>Personvernsretningslinjer</value>
</data>
<data name="AccessibilityDrawOverPermissionAlert" xml:space="preserve">
<value>Bitwarden trenger oppmerksomhet Aktiver "Draw-Over" i "Auto-utfyllingstjenester" fra Bitwarden-innstillinger</value>
@@ -1836,10 +1836,10 @@
<value>Hvis aktivert, vil tilgjengelighet vise en popup for å forsterke Autofill Service for eldre apper som ikke støtter Android Autofill Framework.</value>
</data>
<data name="PersonalOwnershipSubmitError" xml:space="preserve">
<value>På grunn av bedrifsretningslinjer er du begrenset fra å lagre objekter til ditt personlige hvelv. Endre alternativ for eierskap til en organisasjon og velg blant tilgjengelige samlinger.</value>
<value>På grunn av virksomhetsvilkår er du begrenset fra å lagre objekter til ditt personlige hvelv. Endre alternativ for eierskap til en organisasjon og velg blant tilgjengelige samlinger.</value>
</data>
<data name="PersonalOwnershipPolicyInEffect" xml:space="preserve">
<value>En bedriftsretningslinje påvirker dine eierskapsinnstillinger.</value>
<value>Organisasjonsvilkår påvirker dine eierskapsinnstillinger.</value>
</data>
<data name="Send" xml:space="preserve">
<value>Send</value>
@@ -1877,10 +1877,10 @@
<value>Dato for sletting</value>
</data>
<data name="DeletionTime" xml:space="preserve">
<value>Sletting tid</value>
<value>Slettetidspunkt</value>
</data>
<data name="DeletionDateInfo" xml:space="preserve">
<value>Send-en vil bli slettet permanent på den angitte dato og klokkeslett.</value>
<value>Send-en vil bli permanent slettet på angitte dato og klokkeslett.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="PendingDelete" xml:space="preserve">
@@ -1900,7 +1900,7 @@
<value>Utløpt</value>
</data>
<data name="MaximumAccessCount" xml:space="preserve">
<value>Maksimal antall tilganger</value>
<value>Maksimalt antall tilganger</value>
</data>
<data name="MaximumAccessCountInfo" xml:space="preserve">
<value>Hvis satt, vil brukere ikke lenger ha tilgang til dette send når maksimal antall tilgang er nådd.</value>
@@ -1910,13 +1910,13 @@
<value>Maksimalt antall tilganger nådd</value>
</data>
<data name="CurrentAccessCount" xml:space="preserve">
<value>Antall nåværende tilgang</value>
<value>Antall nåværende tilganger</value>
</data>
<data name="NewPassword" xml:space="preserve">
<value>Nytt passord</value>
</data>
<data name="PasswordInfo" xml:space="preserve">
<value>Eventuelt krever et passord for brukere å få tilgang til denne Send.</value>
<value>Valgfritt passordkrav å få tilgang til denne Send.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="RemovePassword" xml:space="preserve">
@@ -1940,18 +1940,18 @@
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="NoSends" xml:space="preserve">
<value>Det er ingen sendinger kontoen din.</value>
<value>Det er ingen Send-er i kontoen din.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="AddASend" xml:space="preserve">
<value>Legg til en sendt</value>
<value>Legg til en Send</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="CopyLink" xml:space="preserve">
<value>Kopier lenke</value>
</data>
<data name="ShareLink" xml:space="preserve">
<value>Del link</value>
<value>Del lenke</value>
</data>
<data name="SendLink" xml:space="preserve">
<value>Send lenke</value>
@@ -2008,7 +2008,7 @@
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SendDisabledWarning" xml:space="preserve">
<value>På grunn av en virksomhetsregel kan du kun slette en eksisterende Send.</value>
<value>På grunn av virksomhetsvilkår kan du kun slette en eksisterende Send.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="AboutSend" xml:space="preserve">
@@ -2019,11 +2019,11 @@
<value>Skjul min e-postadresse fra mottakere.</value>
</data>
<data name="SendOptionsPolicyInEffect" xml:space="preserve">
<value>En eller flere av organisasjons retningslinjer påvirker generatorinnstillingene dine.</value>
<value>En eller flere av organisasjons vilkår påvirker generatorinnstillingene dine.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SendFilePremiumRequired" xml:space="preserve">
<value>Gratis kontoer kan bare dele tekst. Et premiummedlemskap kreves for å bruke filer med Send.</value>
<value>Gratiskontoer kan kun dele tekst. Et premiummedlemskap kreves for å bruke filer med Send.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SendFileEmailVerificationRequired" xml:space="preserve">
@@ -2034,13 +2034,13 @@
<value>Forespørsel om hovedpassord på nytt</value>
</data>
<data name="PasswordConfirmation" xml:space="preserve">
<value>Superpassord bekreftelse</value>
<value>Hovedpassord bekreftelse</value>
</data>
<data name="PasswordConfirmationDesc" xml:space="preserve">
<value>Denne handlingen er beskyttet, for å fortsette å skrive inn superpassordet på nytt for å verifisere din identitet.</value>
<value>Denne handlingen er beskyttet, for å fortsette å skrive inn hovedpassordet på nytt for å verifisere din identitet.</value>
</data>
<data name="CaptchaRequired" xml:space="preserve">
<value>Bekreftelsekode kreves</value>
<value>Captcha kreves</value>
</data>
<data name="CaptchaFailed" xml:space="preserve">
<value>Captcha feilet. Prøv på nytt.</value>
@@ -2094,31 +2094,40 @@
<value>Sørg for at standardnettleseren din støtter WebAuthn og prøv igjen.</value>
</data>
<data name="ResetPasswordAutoEnrollInviteWarning" xml:space="preserve">
<value>Denne organisasjonen har en bedriftsoppsettsregel som automatisk innrullerer deg i tilbakestilling av passord. Registrering vil tillate organisasjonsadministratorer å endre hovedpassordet ditt.</value>
<value>Denne organisasjonen har en virksomhetsvilkår som automatisk innrullerer deg i tilbakestilling av passord. Registrering vil tillate organisasjonsadministratorer å endre hovedpassordet ditt.</value>
</data>
<data name="VaultTimeoutPolicyInEffect" xml:space="preserve">
<value>Din organisasjons retningslinjer påvirker tidsavbruddet for hvelvet. Maksimalt tillatt tidsavbrudd for hvelv er {0} time(r) og {1} minutt(er)</value>
<value>Din organisasjons vikår påvirker tidsavbruddet for hvelvet. Maksimalt tillatt tidsavbrudd for hvelv er {0} time(r) og {1} minutt(er)</value>
</data>
<data name="VaultTimeoutToLarge" xml:space="preserve">
<value>Tidsavbruddet ditt for hvelvet overstiger begrensningene som er satt av organisasjonen din.</value>
</data>
<data name="DisablePersonalVaultExportPolicyInEffect">
<value>En eller flere organisasjonsoppsettsregler hindrer deg i å eksportere ditt personlige hvelv.</value>
<value>En eller flere organisasjonvilkår hindrer deg i å eksportere ditt personlige hvelv.</value>
</data>
<data name="AddAccount" xml:space="preserve">
<value>Add Account</value>
<value>Legg til konto</value>
</data>
<data name="AccountUnlocked" xml:space="preserve">
<value>Unlocked</value>
<value>Ulåst</value>
</data>
<data name="AccountLocked" xml:space="preserve">
<value>Locked</value>
<value>Låst</value>
</data>
<data name="AccountLoggedOut" xml:space="preserve">
<value>Logged Out</value>
<value>Logget av</value>
</data>
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
<value>Byttet til neste tilgjengelige konto</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Konto låst</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Kontoen er logget av</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Kontoen er fjernet</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Slett konto</value>
@@ -2163,9 +2172,9 @@
<value>En verifiseringskode er sendt til din e-post</value>
</data>
<data name="AnErrorOccurredWhileSendingAVerificationCodeToYourEmailPleaseTryAgain" xml:space="preserve">
<value>En feil oppstod ved sending av en verifiseringskode til e-posten. Vennligst prøv igjen</value>
<value>En feil oppstod ved sending av verifiseringskode til e-posten. Vennligst prøv igjen</value>
</data>
<data name="EnterTheVerificationCodeThatWasSentToYourEmail" xml:space="preserve">
<value>Skriv inn bekreftelseskoden som ble sendt til din e-post</value>
<value>Skriv inn verifiseringskoden som ble sendt til din e-post</value>
</data>
</root>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account geblokkeerd</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account succesvol uitgelogd</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account succesvol verwijderd</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Account verwijderen</value>
</data>

View File

@@ -1299,7 +1299,7 @@
<value>1. Go to the iOS "Settings" app</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Tap "Passwords &amp; Accounts"</value>
<value>2. Tap "Passwords"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Tap "AutoFill Passwords"</value>
@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
</data>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Przełączono na następne dostępne konto</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Konto zostało zablokowane</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Wylogowano z konta</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Konto zostało usunięte</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Usuń konto</value>
</data>

View File

@@ -1162,7 +1162,7 @@
<value>Serviço de Acessibilidade de Autopreenchimento</value>
</data>
<data name="AutofillServiceDescription" xml:space="preserve">
<value>O serviço de autopreenchimento do Bitwarden utiliza a Estrutura de Autopreenchimento do Android para ajudar no preenchimento de credenciais, cartões de crédito, e informação de identidade em outros aplicativos do seu dispositivo.</value>
<value>O serviço de autopreenchimento do Bitwarden usa a Estrutura de Preenchimento Automático do Android para auxiliar no preenchimento de credenciais em outros aplicativos no seu dispositivo.</value>
</data>
<data name="BitwardenAutofillServiceDescription" xml:space="preserve">
<value>Use o serviço de acessibilidade do bitwarden para preencher automaticamente suas credenciais.</value>
@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Alterada para a próxima conta disponível</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Conta Bloqueada</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Conta desconectada com sucesso</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Conta removida com sucesso</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Excluir Conta</value>
</data>

View File

@@ -1299,7 +1299,7 @@
<value>1. Go to the iOS "Settings" app</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Tap "Passwords &amp; Accounts"</value>
<value>2. Tap "Passwords"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Tap "AutoFill Passwords"</value>

View File

@@ -1299,7 +1299,7 @@
<value>1. Accesați Setările iOS</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Selectați "Parole și Conturi"</value>
<value>2. Selectați Parole</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Selectați "Auto-completare parole"</value>
@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Comutat la următorul cont disponibil</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Cont blocat</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Contul s-a deconectat cu succes</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Cont eliminat cu succes</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Ștergere cont</value>
</data>

View File

@@ -1299,7 +1299,7 @@
<value>1. Перейдите в 'Настройки' iOS</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Нажмите 'Пароли и учетные записи'</value>
<value>2. Нажмите на пункт "Пароли и учетные записи"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Нажмите 'Автозаполнение паролей'</value>
@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Переключено на следующую доступную учетную запись</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Учетная запись заблокирована</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Вы успешно вышли из учетной записи</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Учетная запись успешно удалена</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Удалить аккаунт</value>
</data>

View File

@@ -1299,7 +1299,7 @@
<value>1. Go to the iOS "Settings" app</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Tap "Passwords &amp; Accounts"</value>
<value>2. Tap "Passwords"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Tap "AutoFill Passwords"</value>
@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
</data>

View File

@@ -1428,7 +1428,7 @@
<value>Počet slov</value>
</data>
<data name="Passphrase" xml:space="preserve">
<value>Heslo</value>
<value>Prístupová fráza</value>
</data>
<data name="WordSeparator" xml:space="preserve">
<value>Oddeľovač slov</value>
@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Prepnuté na ďalší dostupný účet</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Zamknutý účet</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Účet bol úspešne odhlásený</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Účet bol úspešne odstránený</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Odstrániť účet</value>
</data>

View File

@@ -1299,7 +1299,7 @@
<value>1. Pojdite v nastavitve iOS aplikacije</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Tap "Passwords &amp; Accounts"</value>
<value>2. Tap "Passwords"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Tap "AutoFill Passwords"</value>
@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Izbriši račun</value>
</data>

View File

@@ -2121,6 +2121,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Пребацили сте се на следећи доступни налог</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Налог закључан</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Успешно одјављивање</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Налог je успешно уклоњен</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Избриши Налог</value>
</data>

View File

@@ -1162,10 +1162,10 @@
<value>Tillgänglighetstjänst för automatisk ifyllnad</value>
</data>
<data name="AutofillServiceDescription" xml:space="preserve">
<value>Bitwardens tillgänglighetstjänst för automatisk ifyllnad använder Android Autofill Framework för att assistera med att fylla i inloggningar, kreditkort och identitetsinformation inuti andra appar på din enhet.</value>
<value>The Bitwarden auto-fill service uses the Android Autofill Framework to assist in filling login information into other apps on your device.</value>
</data>
<data name="BitwardenAutofillServiceDescription" xml:space="preserve">
<value>Använd Bitwardens tillgänglighetstjänst för att automatiskt fylla i inloggningar, kreditkort och identitetsinformation inuti andra appar.</value>
<value>Use the Bitwarden auto-fill service to fill login information into other apps.</value>
</data>
<data name="BitwardenAutofillServiceOpenAutofillSettings" xml:space="preserve">
<value>Öppna inställningar för automatisk ifyllnad</value>
@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Radera konto</value>
</data>

View File

@@ -1300,7 +1300,7 @@
<value>௧. iOS "அமைவுகள்" செயலிக்குச் செல்</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. "கடவுச்சொற்கள் &amp; கணக்குகள்"ஐத் தட்டு</value>
<value>2. "கடவுச்சொற்கள்"ஐத் தட்டு</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. "கடவுச்சொற்கள் தன்னிரப்பல்"ஐத் தட்டு</value>
@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>அடுத்து கிடைத்த கணக்கிற்கு நிலைமாறியது</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>கணக்கை அழி</value>
</data>

View File

@@ -1299,7 +1299,7 @@
<value>1. Go to the iOS "Settings" app</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Tap "Passwords &amp; Accounts"</value>
<value>2. Tap "Passwords"</value>
</data>
<data name="AutofillTurnOn3" xml:space="preserve">
<value>3. Tap "AutoFill Passwords"</value>
@@ -2120,6 +2120,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
</data>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Bir sonraki hesaba geçildi</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Hesap kilitlendi</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Başarıyla çıkış yapıldı</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Hesap başarıyla kaldırıldı</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Hesabı sil</value>
</data>

View File

@@ -276,16 +276,16 @@
<value>Ви дійсно хочете вийти?</value>
</data>
<data name="RemoveAccount" xml:space="preserve">
<value>Remove Account</value>
<value>Вилучити обліковий запис</value>
</data>
<data name="RemoveAccountConfirmation" xml:space="preserve">
<value>Are you sure you want to remove this account?</value>
<value>Ви дійсно хочете вилучити цей обліковий запис?</value>
</data>
<data name="AccountAlreadyAdded" xml:space="preserve">
<value>Account Already Added</value>
<value>Обліковий запис вже додано</value>
</data>
<data name="SwitchToAlreadyAddedAccountConfirmation" xml:space="preserve">
<value>Would you like to switch to it now?</value>
<value>Бажаєте перемкнутися на нього зараз?</value>
</data>
<data name="MasterPassword" xml:space="preserve">
<value>Головний пароль</value>
@@ -1162,10 +1162,10 @@
<value>Служба спеціальних можливостей автозаповнення</value>
</data>
<data name="AutofillServiceDescription" xml:space="preserve">
<value>Служба автозаповнення Bitwarden використовує Android Autofill Framework для заповнення паролів, кредитних карток та особистої інформації в інших програмах на вашому пристрої.</value>
<value>Служба автозаповнення Bitwarden використовує Android Autofill Framework для введення облікових даних в інших програмах на вашому пристрої.</value>
</data>
<data name="BitwardenAutofillServiceDescription" xml:space="preserve">
<value>Використовуйте службу автозаповнення Bitwarden, щоб автоматично вводити паролі, кредитні картки та особисту інформацію в інших програмах.</value>
<value>Використовуйте службу автозаповнення Bitwarden, щоб автоматично вводити облікові дані в інших програмах.</value>
</data>
<data name="BitwardenAutofillServiceOpenAutofillSettings" xml:space="preserve">
<value>Відкрити налаштування автозаповнення</value>
@@ -1935,7 +1935,7 @@
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="DisableSend" xml:space="preserve">
<value>Деактивувати це відправлення для скасування доступу до нього.</value>
<value>Деактивувати це відправлення для скасування доступу до нього</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="NoSends" xml:space="preserve">
@@ -2003,7 +2003,7 @@
<value>Спеціальний</value>
</data>
<data name="ShareOnSave" xml:space="preserve">
<value>Поділитися цим відправленням після збереження.</value>
<value>Поділитися цим відправленням після збереження</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="SendDisabledWarning" xml:space="preserve">
@@ -2015,7 +2015,7 @@
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data>
<data name="HideEmail" xml:space="preserve">
<value>Приховувати мою адресу електронної пошти від отримувачів.</value>
<value>Приховувати мою адресу електронної пошти від отримувачів</value>
</data>
<data name="SendOptionsPolicyInEffect" xml:space="preserve">
<value>На параметри відправлень впливають одна чи декілька політик організації.</value>
@@ -2105,19 +2105,28 @@
<value>Одна чи декілька організаційних політик не дозволяють вам експортувати особисте сховище.</value>
</data>
<data name="AddAccount" xml:space="preserve">
<value>Add Account</value>
<value>Додати обліковий запис</value>
</data>
<data name="AccountUnlocked" xml:space="preserve">
<value>Unlocked</value>
<value>Розблоковано</value>
</data>
<data name="AccountLocked" xml:space="preserve">
<value>Locked</value>
<value>Заблоковано</value>
</data>
<data name="AccountLoggedOut" xml:space="preserve">
<value>Logged Out</value>
<value>Ви вийшли з системи</value>
</data>
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
<value>Ви перемкнулися на інший доступний обліковий запис</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Обліковий запис заблоковано</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Ви успішно вийшли з облікового запису</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Обліковий запис успішно вилучено</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Видалити обліковий запис</value>

View File

@@ -2119,6 +2119,15 @@
<data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value>
</data>
<data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value>
</data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value>
</data>
<data name="AccountRemovedSuccessfully" xml:space="preserve">
<value>Account removed successfully</value>
</data>
<data name="DeleteAccount" xml:space="preserve">
<value>Delete Account</value>
</data>

File diff suppressed because it is too large Load Diff

View File

@@ -29,6 +29,8 @@ namespace Bit.App.Services
Constants.iOSAutoFillBiometricIntegrityKey,
Constants.iOSExtensionClearCiphersCacheKey,
Constants.iOSExtensionBiometricIntegrityKey,
Constants.iOSShareExtensionClearCiphersCacheKey,
Constants.iOSShareExtensionBiometricIntegrityKey,
Constants.RememberedEmailKey,
Constants.RememberedOrgIdentifierKey,
};

View File

@@ -92,7 +92,7 @@
<Setter Property="TextColor"
Value="{DynamicResource ButtonTextColor}" />
<Setter Property="FontSize"
Value="18" />
Value="Medium" />
<Setter Property="CornerRadius"
Value="5" />
<Setter Property="Margin"
@@ -126,7 +126,7 @@
<Setter Property="TextColor"
Value="{DynamicResource ButtonPrimaryTextColor}" />
<Setter Property="FontSize"
Value="18" />
Value="Medium" />
<Setter Property="FontAttributes"
Value="Bold" />
<Setter Property="CornerRadius"
@@ -298,6 +298,18 @@
<Setter Property="FontSize"
Value="25" />
</Style>
<Style TargetType="Label"
Class="accountlist-title-platform"
ApplyToDerivedTypes="True">
<Setter Property="FontSize"
Value="Body" />
</Style>
<Style TargetType="Label"
Class="accountlist-sub-platform"
ApplyToDerivedTypes="True">
<Setter Property="FontSize"
Value="Caption" />
</Style>
<!-- Box -->

View File

@@ -221,6 +221,14 @@
<Setter Property="TextColor"
Value="{DynamicResource MutedColor}" />
</Style>
<Style TargetType="Label"
Class="accountlist-title">
</Style>
<Style TargetType="Label"
Class="accountlist-sub">
<Setter Property="TextColor"
Value="{DynamicResource MutedColor}" />
</Style>
<Style TargetType="Label"
ApplyToDerivedTypes="True"
Class="list-title-icon">

View File

@@ -105,7 +105,7 @@
<Setter Property="TextColor"
Value="{DynamicResource ButtonTextColor}" />
<Setter Property="FontSize"
Value="18" />
Value="Medium" />
<Setter Property="Margin"
Value="0, 5, 0, 0" />
<Setter Property="VisualStateManager.VisualStateGroups">
@@ -143,7 +143,7 @@
<Setter Property="TextColor"
Value="{DynamicResource ButtonPrimaryTextColor}" />
<Setter Property="FontSize"
Value="18" />
Value="Medium" />
<Setter Property="FontAttributes"
Value="Bold" />
<Setter Property="Margin"
@@ -320,6 +320,16 @@
<Setter Property="FontSize"
Value="25" />
</Style>
<Style TargetType="Label"
Class="accountlist-title-platform"
ApplyToDerivedTypes="True">
</Style>
<Style TargetType="Label"
Class="accountlist-sub-platform"
ApplyToDerivedTypes="True">
<Setter Property="FontSize"
Value="Small" />
</Style>
<!-- Box -->

View File

@@ -502,41 +502,25 @@ namespace Bit.App.Utilities
public static async Task LogOutAsync(string userId, bool userInitiated = false)
{
var tokenService = ServiceContainer.Resolve<ITokenService>("tokenService");
var cryptoService = ServiceContainer.Resolve<ICryptoService>("cryptoService");
var settingsService = ServiceContainer.Resolve<ISettingsService>("settingsService");
var cipherService = ServiceContainer.Resolve<ICipherService>("cipherService");
var folderService = ServiceContainer.Resolve<IFolderService>("folderService");
var collectionService = ServiceContainer.Resolve<ICollectionService>("collectionService");
var passwordGenerationService = ServiceContainer.Resolve<IPasswordGenerationService>(
"passwordGenerationService");
var vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
var stateService = ServiceContainer.Resolve<IStateService>("stateService");
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
var policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
var searchService = ServiceContainer.Resolve<ISearchService>("searchService");
var vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
var isActiveAccount = await stateService.IsActiveAccountAsync(userId);
var isAccountRemoval = await vaultTimeoutService.IsLoggedOutByTimeoutAsync(userId) ||
await vaultTimeoutService.ShouldLogOutByTimeoutAsync(userId);
if (userId == null)
{
userId = await stateService.GetActiveUserIdAsync();
}
await Task.WhenAll(
cipherService.ClearAsync(userId),
folderService.ClearAsync(userId),
collectionService.ClearAsync(userId),
passwordGenerationService.ClearAsync(userId),
deviceActionService.ClearCacheAsync(),
tokenService.ClearTokenAsync(userId),
cryptoService.ClearKeysAsync(userId),
settingsService.ClearAsync(userId),
vaultTimeoutService.ClearAsync(userId),
policyService.ClearAsync(userId),
stateService.LogoutAccountAsync(userId, userInitiated));
await stateService.LogoutAccountAsync(userId, userInitiated);
searchService.ClearIndex();
if (isActiveAccount)
{
await ClearServiceCacheAsync();
}
if (!userInitiated)
{
@@ -558,8 +542,7 @@ namespace Bit.App.Utilities
if (!isActiveAccount)
{
var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
if (await vaultTimeoutService.IsLoggedOutByTimeoutAsync(userId) ||
await vaultTimeoutService.ShouldLogOutByTimeoutAsync())
if (isAccountRemoval)
{
platformUtilsService.ShowToast("info", null, AppResources.AccountRemovedSuccessfully);
return;
@@ -571,6 +554,14 @@ namespace Bit.App.Utilities
public static async Task OnAccountSwitchAsync()
{
var environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
await environmentService.SetUrlsFromStorageAsync();
await ClearServiceCacheAsync();
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
await deviceActionService.OnAccountSwitchCompleteAsync();
}
public static async Task ClearServiceCacheAsync()
{
var tokenService = ServiceContainer.Resolve<ITokenService>("tokenService");
var cryptoService = ServiceContainer.Resolve<ICryptoService>("cryptoService");
var settingsService = ServiceContainer.Resolve<ISettingsService>("settingsService");
@@ -584,8 +575,6 @@ namespace Bit.App.Utilities
var policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
var searchService = ServiceContainer.Resolve<ISearchService>("searchService");
await environmentService.SetUrlsFromStorageAsync();
await Task.WhenAll(
cipherService.ClearCacheAsync(),
deviceActionService.ClearCacheAsync());

View File

@@ -55,6 +55,7 @@ namespace Bit.Core.Abstractions
Task SetAutofillTileAddedAsync(bool? value);
Task<string> GetEmailAsync(string userId = null);
Task<string> GetNameAsync(string userId = null);
Task SetNameAsync(string value, string userId = null);
Task<string> GetOrgIdentifierAsync(string userId = null);
Task<long?> GetLastActiveTimeAsync(string userId = null);
Task SetLastActiveTimeAsync(long? value, string userId = null);
@@ -62,8 +63,8 @@ namespace Bit.Core.Abstractions
Task SetVaultTimeoutAsync(int? value, string userId = null);
Task<VaultTimeoutAction?> GetVaultTimeoutActionAsync(string userId = null);
Task SetVaultTimeoutActionAsync(VaultTimeoutAction? value, string userId = null);
Task<DateTime?> GetLastFileCacheClearAsync(string userId = null);
Task SetLastFileCacheClearAsync(DateTime? value, string userId = null);
Task<DateTime?> GetLastFileCacheClearAsync();
Task SetLastFileCacheClearAsync(DateTime? value);
Task<PreviousPageInfo> GetPreviousPageInfoAsync(string userId = null);
Task SetPreviousPageInfoAsync(PreviousPageInfo value, string userId = null);
Task<int> GetInvalidUnlockAttemptsAsync(string userId = null);

View File

@@ -23,6 +23,8 @@
public static string iOSAutoFillBiometricIntegrityKey = "iOSAutoFillBiometricIntegrityState";
public static string iOSExtensionClearCiphersCacheKey = "iOSExtensionClearCiphersCache";
public static string iOSExtensionBiometricIntegrityKey = "iOSExtensionBiometricIntegrityState";
public static string iOSShareExtensionClearCiphersCacheKey = "iOSShareExtensionClearCiphersCache";
public static string iOSShareExtensionBiometricIntegrityKey = "iOSShareExtensionBiometricIntegrityState";
public static string EventCollectionKey = "eventCollection";
public static string RememberedEmailKey = "rememberedEmail";
public static string RememberedOrgIdentifierKey = "rememberedOrgIdentifier";
@@ -39,7 +41,8 @@
{
ClearCiphersCacheKey,
iOSAutoFillClearCiphersCacheKey,
iOSExtensionClearCiphersCacheKey
iOSExtensionClearCiphersCacheKey,
iOSShareExtensionClearCiphersCacheKey
};
public static string CiphersKey(string userId) => $"ciphers_{userId}";

View File

@@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Models.Data;
using Bit.Core.Models.Domain;
using Bit.Core.Utilities;
using Newtonsoft.Json;
namespace Bit.Core.Services
{
@@ -354,7 +352,6 @@ namespace Bit.Core.Services
private async Task<T> GetValueAsync<T>(Storage storage, string key)
{
var value = await GetStorageService(storage).GetAsync<T>(key);
Log("GET", storage, key, JsonConvert.SerializeObject(value));
return value;
}
@@ -365,13 +362,11 @@ namespace Bit.Core.Services
await RemoveValueAsync(storage, key);
return;
}
Log("SET", storage, key, JsonConvert.SerializeObject(value));
await GetStorageService(storage).SaveAsync(key, value);
}
private async Task RemoveValueAsync(Storage storage, string key)
{
Log("REMOVE", storage, key, null);
await GetStorageService(storage).RemoveAsync(key);
}
@@ -387,29 +382,5 @@ namespace Bit.Core.Services
return _liteDbStorageService;
}
}
private void Log(string tag, Storage storage, string key, string value)
{
// TODO Remove this once all bugs are squished
string text;
switch (storage)
{
case Storage.Secure:
text = "SECURE / ";
break;
case Storage.Prefs:
text = "PREFS / ";
break;
default:
text = "LITEDB / ";
break;
}
text += "Key: " + key + " / ";
if (value != null)
{
text += "Value: " + value;
}
Debug.WriteLine(text, ">>> " + tag);
}
}
}

View File

@@ -1,7 +1,6 @@
using System;
using Bit.Core.Abstractions;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Bit.Core.Enums;
@@ -9,7 +8,6 @@ using Bit.Core.Models.Data;
using Bit.Core.Models.Domain;
using Bit.Core.Models.View;
using Bit.Core.Utilities;
using Newtonsoft.Json;
namespace Bit.Core.Services
{
@@ -48,7 +46,6 @@ namespace Bit.Core.Services
{
return true;
}
await CheckStateAsync();
return userId == await GetActiveUserIdAsync();
}
@@ -160,8 +157,9 @@ namespace Bit.Core.Services
await CheckStateAsync();
await RemoveAccountAsync(userId, userInitiated);
// If user initiated logout (not vault timeout) find the next user to make active, if any
if (userInitiated && _state?.Accounts != null)
// If user initiated logout (not vault timeout) and ActiveUserId is null after account removal, find the
// next user to make active, if any
if (userInitiated && _state?.ActiveUserId == null && _state?.Accounts != null)
{
foreach (var account in _state.Accounts)
{
@@ -470,6 +468,15 @@ namespace Bit.Core.Services
))?.Profile?.Name;
}
public async Task SetNameAsync(string value, string userId = null)
{
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
await GetDefaultStorageOptionsAsync());
var account = await GetAccountAsync(reconciledOptions);
account.Profile.Name = value;
await SaveAccountAsync(account, reconciledOptions);
}
public async Task<string> GetOrgIdentifierAsync(string userId = null)
{
return (await GetAccountAsync(
@@ -525,20 +532,18 @@ namespace Bit.Core.Services
await SaveAccountAsync(account, reconciledOptions);
}
public async Task<DateTime?> GetLastFileCacheClearAsync(string userId = null)
public async Task<DateTime?> GetLastFileCacheClearAsync()
{
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
await GetDefaultStorageOptionsAsync());
var options = await GetDefaultStorageOptionsAsync();
var key = Constants.LastFileCacheClearKey;
return await GetValueAsync<DateTime?>(key, reconciledOptions);
return await GetValueAsync<DateTime?>(key, options);
}
public async Task SetLastFileCacheClearAsync(DateTime? value, string userId = null)
public async Task SetLastFileCacheClearAsync(DateTime? value)
{
var reconciledOptions = ReconcileOptions(new StorageOptions { UserId = userId },
await GetDefaultStorageOptionsAsync());
var options = await GetDefaultStorageOptionsAsync();
var key = Constants.LastFileCacheClearKey;
await SetValueAsync(key, value, reconciledOptions);
await SetValueAsync(key, value, options);
}
public async Task<PreviousPageInfo> GetPreviousPageInfoAsync(string userId = null)
@@ -1176,25 +1181,26 @@ namespace Bit.Core.Services
private async Task<T> GetValueAsync<T>(string key, StorageOptions options)
{
var value = await GetStorageService(options).GetAsync<T>(key);
Log("GET", options, key, JsonConvert.SerializeObject(value));
return value;
return await GetStorageService(options).GetAsync<T>(key);
}
private async Task SetValueAsync<T>(string key, T value, StorageOptions options)
{
if (value == null)
{
Log("REMOVE", options, key, null);
await GetStorageService(options).RemoveAsync(key);
return;
}
Log("SET", options, key, JsonConvert.SerializeObject(value));
await GetStorageService(options).SaveAsync(key, value);
}
private async Task SetValueGloballyAsync<T>(Func<string, string> keyPrefix, T value, StorageOptions options)
{
if (value == null)
{
// don't remove values globally
return;
}
await CheckStateAsync();
if (_state?.Accounts == null)
{
@@ -1237,14 +1243,11 @@ namespace Bit.Core.Services
}
// Storage
_state = await GetStateFromStorageAsync();
if (_state?.Accounts?.ContainsKey(options.UserId) ?? false)
var state = await GetStateFromStorageAsync();
if (state?.Accounts?.ContainsKey(options.UserId) ?? false)
{
if (_state.Accounts[options.UserId].VolatileData == null)
{
_state.Accounts[options.UserId].VolatileData = new Account.AccountVolatileData();
}
return _state.Accounts[options.UserId];
state.Accounts[options.UserId].VolatileData = new Account.AccountVolatileData();
return state.Accounts[options.UserId];
}
return null;
@@ -1312,8 +1315,7 @@ namespace Bit.Core.Services
{
_state.Accounts[userId].Tokens.AccessToken = null;
_state.Accounts[userId].Tokens.RefreshToken = null;
_state.Accounts[userId].VolatileData.Key = null;
_state.Accounts[userId].VolatileData.BiometricLocked = null;
_state.Accounts[userId].VolatileData = null;
}
}
if (userInitiated && _state?.ActiveUserId == userId)
@@ -1357,7 +1359,6 @@ namespace Bit.Core.Services
await SetOrgKeysEncryptedAsync(null, userId);
await SetPrivateKeyEncryptedAsync(null, userId);
await SetLastActiveTimeAsync(null, userId);
await SetLastFileCacheClearAsync(null, userId);
await SetPreviousPageInfoAsync(null, userId);
await SetInvalidUnlockAttemptsAsync(null, userId);
await SetLocalDataAsync(null, userId);
@@ -1505,19 +1506,12 @@ namespace Bit.Core.Services
private async Task<State> GetStateFromStorageAsync()
{
var state = await _storageService.GetAsync<State>(Constants.StateKey);
// TODO Remove logging once all bugs are squished
Debug.WriteLine(JsonConvert.SerializeObject(state, Formatting.Indented),
">>> GetStateFromStorageAsync()");
return state;
return await _storageService.GetAsync<State>(Constants.StateKey);
}
private async Task SaveStateToStorageAsync(State state)
{
await _storageService.SaveAsync(Constants.StateKey, state);
// TODO Remove logging once all bugs are squished
Debug.WriteLine(JsonConvert.SerializeObject(state, Formatting.Indented),
">>> SaveStateToStorageAsync()");
}
private async Task CheckStateAsync()
@@ -1560,17 +1554,5 @@ namespace Bit.Core.Services
}
throw new Exception("User does not exist in account list");
}
private void Log(string tag, StorageOptions options, string key, string value)
{
// TODO Remove this once all bugs are squished
var text = options?.UseSecureStorage ?? false ? "SECURE / " : "";
text += "Key: " + key + " / ";
if (value != null)
{
text += "Value: " + value;
}
Debug.WriteLine(text, ">>> " + tag);
}
}
}

View File

@@ -327,6 +327,7 @@ namespace Bit.Core.Services
var organizations = response.Organizations.ToDictionary(o => o.Id, o => new OrganizationData(o));
await _organizationService.ReplaceAsync(organizations);
await _stateService.SetEmailVerifiedAsync(response.EmailVerified);
await _stateService.SetNameAsync(response.Name);
await _keyConnectorService.SetUsesKeyConnector(response.UsesKeyConnector);
}

View File

@@ -208,6 +208,10 @@ namespace Bit.Core.Services
if (_accessTokenForDecoding == null)
{
await GetTokenAsync();
if (_accessTokenForDecoding == null)
{
return false;
}
}
var decoded = DecodeToken();
if (decoded?["amr"] == null)

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