1
0
mirror of https://github.com/bitwarden/mobile synced 2026-01-01 08:03:37 +00:00

Compare commits

..

48 Commits

Author SHA1 Message Date
Bitwarden DevOps
ffd888bd96 Bumped version to 2024.3.0 (#3080)
(cherry picked from commit e7f9d64edb)
2024-03-14 11:15:28 -04:00
Federico Maccaroni
95f66870c2 [PM-6751]Added missing query intent for CustomTabs that might be responsible for the Exception in WebAuthenticator 2024-03-11 19:37:04 -03:00
Federico Maccaroni
0bd4e62afd [PM-6726] Fix for Android 14 devices crashing when using the Tiles 2024-03-11 18:07:40 -03:00
Vince Grassia
e3441845cd DEVOPS-1866 - Fix F-Droid Signing (#3063) 2024-03-07 23:45:15 +00:00
Vince Grassia
3f463647a0 Add login step to be able to download secrets (#3061) 2024-03-07 07:18:32 -08:00
Bitwarden DevOps
4f169a6fe3 Bumped version to 2024.2.2 (#3060) 2024-03-07 15:07:46 +00:00
Vince Grassia
82c2e91446 Update release workflow with proper paths (#3059) 2024-03-07 15:53:27 +01:00
renovate[bot]
7482808857 [deps]: Update chrnorm/deployment-status action to v2.0.3 (#3050)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-06 13:52:31 -05:00
Opeyemi
fd233fa27f Update Failure Job (#3055) 2024-03-06 13:58:41 +01:00
Federico Maccaroni
19f238d9bb [PM-6539] Fix Autofill Extension TDE without MP flow (#3049)
* PM-6539 Fix Autofill Extension TDE without MP updating PromptSSO to work in MAUI and also Generator view. WebAuthenticator copied with UIWindow gotten as it was in Xamarin forms to work. Also fix one NRE on state migration.

* PM-6539 Remove unnecessary using
2024-03-05 18:09:20 -03:00
Vince Grassia
6f6487ccc9 Fix GoogleServices file location (#3053) 2024-03-04 08:11:54 -07:00
Dinis Vieira
dd3dc82595 PM-6552 Added missing using (#3052) 2024-03-04 13:29:22 +00:00
Dinis Vieira
40c80f082d [PM-6552] Fix for Android Window issues when opening Autofill/Accessibility (#3051)
* PM-6552 Removed several of the Window Workarounds for Android. Now always relying on the AndroidNavigationRedirectPage.
AndroidNavigationRedirectPage now more resilient to failure and navigates to HomePage as fallback.

* Update src/Core/Pages/AndroidNavigationRedirectPage.xaml.cs

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

---------

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
2024-03-04 13:03:09 +00:00
André Bispo
bca5b95446 [PM-4760] Admin Recovery Permissions prompted to set MP. (#2912)
* [PM-4760] Add force password reset check on sync complete.

* [PM-4760] Log error on exception
2024-03-01 19:43:18 +00:00
Dinis Vieira
602627b5fa PM-6552 Fix for App only showing Home (Login) Page after closed after opening Accessibility Settings (#3047) 2024-03-01 19:17:45 +00:00
github-actions[bot]
6f32afb919 Autosync the updated translations (#3045)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-03-01 12:26:42 +01:00
Daniel James Smith
2ca47a4da4 Update ownership of translations (#3046)
Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
2024-03-01 11:10:15 +00:00
Dinis Vieira
4ff56ba11e PM-5916 Fix for incorrect fonts in fingerprint phrases (#3042) 2024-02-29 09:57:25 +00:00
Vince Grassia
22d0cc681c Change version to proper value (#3041) 2024-02-28 11:49:30 -07:00
André Bispo
4e0a18cce5 [PM-6506] Fix double execution of command on returnType Go (#3039)
* [PM-6506] Fix double execution of command on returnType Go

* [PM-6506] Hide keyboard on environment page close

* [PM-6506] Task guard

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>

---------

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
2024-02-28 17:49:46 +00:00
Vince Grassia
c9fdfa7a15 DEVOPS-1746 - Update iOS distribution certificate and profiles (#3018) 2024-02-28 09:48:16 -03:00
Vince Grassia
850a7e754a DEVOPS-1834 - Apply fix for signing issue (#3038) 2024-02-27 20:18:24 +00:00
Dinis Vieira
67c5f79625 [PM-5917] Fix for send arrow now being touch sensitive to expand collapse (#3036)
* PM-5917 fix for send arrow not being tappable

* Added min width to send icon button so that it has correct spacing like in Android and old Xamarin Forms app.

* Updated min width from previous commit to 25 instead of 20 for more equivalent look to xamarin forms app on iOS
2024-02-26 23:45:59 +00:00
Federico Maccaroni
04e7cfe06d [PM-6428] Implement Legacy Secure Storage (#3027) 2024-02-26 19:25:08 -03:00
Álison Fernandes
d6c2ebe4c2 [PM-6480] Update MAUI to 8.0.7 (#3035)
* Update MAUI to 8.0.7

Updates MAUI to the future SR2 release version.

* Using the released version instead of nightly
2024-02-26 22:24:44 +00:00
Dinis Vieira
2a28294f91 PM-5912 Added default min height and corner radius for iOS buttons. Also removed incorrect style class from one button. (#3031) 2024-02-26 19:23:06 -03:00
Dinis Vieira
8584bbaecc PM-6301 Removed IsRefreshing=true in RefreshAsync as it can trigger the RefreshView to trigger the RefreshView command again (#3026) 2024-02-26 17:28:18 +00:00
Dinis Vieira
2f3cded9c5 PM-6309 Fix to ensure the Icon and Icon placeholder visibility states is updated correctly based on website icons visibility choice (#3033) 2024-02-26 17:16:54 +00:00
github-actions[bot]
eff0ea7ce7 Autosync the updated translations (#3025)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2024-02-26 15:29:26 +00:00
renovate[bot]
6c3a53dd76 [deps]: Update dawidd6/action-download-artifact action to v3.1.2 (#3028)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-26 09:37:03 -05:00
Vince Grassia
cf8d801c55 Add .NET 3.1 to fix Google Publisher project signing (#3024) 2024-02-22 13:45:42 -07:00
Federico Maccaroni
eaa6844742 Update build.yml to go back to net3.1 Publisher (#3023) 2024-02-22 17:01:33 -03:00
Federico Maccaroni
29e2f728e0 Update Publisher.csproj to go back to net 3.1 to see if that fixes the build (#3022) 2024-02-22 16:39:09 -03:00
Opeyemi
fe160a570f Add stub for DEVOPS-1822 (#3016) 2024-02-21 15:27:43 +00:00
Dinis Vieira
a508bea4b0 [PM-6291] Fix Device Login Pending Requests screen not displaying anything (#3012)
* PM-6291 Changed Passwordless Request Login Page Layout structure so that it can display properly

* PM-6291 Additional changes to allow iOS to show the correct with on the collectionview items
2024-02-21 10:55:26 +00:00
Dinis Vieira
a73923c4f7 [PM-5909] Fix Font MAUI Sizes (#3014)
* PM-5909 Set the default FontSize for Entry, Editor, SearchBar and Picker on Android so that the fonts have a similar size to the one in the Xamarin Forms app.

* PM-5909 Set the default FontSize for Entry, Editor, SearchBar and Picker on iOS so that the fonts have a similar size to the one in the Xamarin Forms app.

* PM-5909 Added spacing in specific scenario for Send Groups (between icon and text)
2024-02-20 22:06:47 +00:00
renovate[bot]
11465e8975 [deps]: Update gh minor (#3011)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-20 16:01:34 -05:00
André Bispo
4c88524f0e [PM-4615] [PM-6217] Add new DUO frameless 2fa flow (#2956)
* [PM-4615] Update DUO 2FA screen to support DUO frameless flow.
2024-02-20 18:46:47 +00:00
Opeyemi
f1c20e03bc Remove individual linter file (#3010) 2024-02-15 11:15:13 -05:00
github-actions[bot]
920a2273c5 Autosync Crowdin Translations (#3009)
* Autosync the updated translations

* Add whitespace to build.yml to trigger workflow linter

* Remove whitespace from build.yml

---------

Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
2024-02-15 12:52:13 -03:00
mpbw2
96a9978ef8 fix resources path for crowdin (#3008) 2024-02-14 10:26:36 -05:00
Dinis Vieira
1ae388cb03 [PM-5900] Fix for Device Login push notifications cause the app to show HomePage (#2989)
* PM-5900 Fix for Device Login push notifications cause the app to show the HomePage

* PM-5900 Added edge case scenario if intent / packageName / packageManager is null
2024-02-13 22:07:09 +00:00
Vince Grassia
c6aaf5002f Add xmllint install step (#3006) 2024-02-12 12:37:52 -07:00
Bitwarden DevOps
75be6504e1 Bumped version to 2024.2.2 (#3005) 2024-02-12 19:20:44 +00:00
renovate[bot]
cae1825e3f [deps]: Update gh minor (#2992)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-12 14:09:14 -05:00
Vince Grassia
c23100d281 Update CODEOWNERS file for Version Bump automation (#3004) 2024-02-12 14:03:12 -05:00
Vince Grassia
c9c0d0b4d6 Fix while loop (#3003) 2024-02-12 18:20:29 +00:00
mpbw2
fec0743e4d Fix for Android builds (#3001)
* enable unit test flag

* revert UT flag and modify flags in ThemeManager
2024-02-12 12:45:52 -05:00
144 changed files with 2637 additions and 628 deletions

10
.github/CODEOWNERS vendored
View File

@@ -11,11 +11,11 @@
.github/workflows @bitwarden/dept-devops .github/workflows @bitwarden/dept-devops
# DevOps for Version Bumping # DevOps for Version Bumping
src/Android/Properties/AndroidManifest.xml src/App/Platforms/Android/AndroidManifest.xml
src/iOS.Autofill/Info.plist src/iOS.Autofill/Info.plist
src/iOS.Extension/Info.plist src/iOS.Extension/Info.plist
src/iOS.ShareExtension/Info.plist src/iOS.ShareExtension/Info.plist
src/iOS/Info.plist src/App/Platforms/iOS/Info.plist
## Auth team files ## ## Auth team files ##
@@ -30,14 +30,14 @@ src/watchOS @bitwarden/team-vault-dev
src/Core/Services/EmailForwarders @bitwarden/team-tools-dev src/Core/Services/EmailForwarders @bitwarden/team-tools-dev
## Crowdin Sync files ## ## Crowdin Sync files ##
src/App/Resources @bitwarden/team-tools-dev src/Core/Resources/Localization @bitwarden/team-tools-dev
src/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization @bitwarden/team-tools-dev src/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization @bitwarden/team-tools-dev
store/apple @bitwarden/team-tools-dev store/apple @bitwarden/team-tools-dev
store/google @bitwarden/team-tools-dev store/google @bitwarden/team-tools-dev
## Locales ## ## Locales ##
src/App/Resources/AppResources.Designer.cs src/Core/Resources/Localization/AppResources.Designer.cs
src/App/Resources/AppResources.resx src/Core/Resources/Localization/AppResources.resx
src/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization/en.lproj src/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization/en.lproj
store/apple/en store/apple/en
store/google/en store/google/en

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,3 +0,0 @@
<EFBFBD>
 K<>Y#<23>(<28><><EFBFBD><EFBFBD>EI֐߄T?)l<><6C><EFBFBD><18><><10>"=<3D>|<7C>'e<><0E>m<EFBFBD>/~<7E><>' F<><46>><3E><><EFBFBD><EFBFBD>l<EFBFBD>b<EFBFBD>[<5B>+R<><52>iL<69><4C>"<22><><EFBFBD>~V:<3A><>p<EFBFBD>a<17>ڵel%8t<38><74><EFBFBD>y<<3C>n<EFBFBD><6E><EFBFBD>aU<61>w<16>JD<4A><44><1F><>We<57>9<EFBFBD><39><EFBFBD><EFBFBD><x8d<38>O<EFBFBD>j\<14>ד<EFBFBD><D793><EFBFBD>Vq<56><71>֋
Ǻ<EFBFBD>-<2D>#<23><><11><>]$<24>(<28>l,<2C>Br<42><02><>d<><64><EFBFBD>•a-<2D><><EFBFBD>:<3A><>:<3A><04>9b,!Em<02><19><>Qf<>D<EFBFBD>g<EFBFBD><06><0E>x(P<>ȡ~<7E>͹<EFBFBD><CDB9> <09><>[<06><>!:<3A>;f<><66>

Binary file not shown.

Binary file not shown.

Binary file not shown.

5
.github/workflows/build-beta.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
---
name: Build Beta
on:
workflow_dispatch:

View File

@@ -31,6 +31,7 @@ jobs:
- name: Print lines of code - name: Print lines of code
run: cloc --vcs git --exclude-dir Resources,store,test,Properties --include-lang C#,XAML run: cloc --vcs git --exclude-dir Resources,store,test,Properties --include-lang C#,XAML
setup: setup:
name: Setup name: Setup
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
@@ -58,6 +59,7 @@ jobs:
echo "hotfix_branch_exists=0" >> $GITHUB_OUTPUT echo "hotfix_branch_exists=0" >> $GITHUB_OUTPUT
fi fi
android: android:
name: Android name: Android
runs-on: windows-2022 runs-on: windows-2022
@@ -67,7 +69,8 @@ jobs:
matrix: matrix:
variant: ["prod", "qa"] variant: ["prod", "qa"]
env: env:
android_folder_path: src/App/Platforms/Android android_folder_path: src\App\Platforms\Android
android_folder_path_bash: src/App/Platforms/Android
steps: steps:
- name: Setup NuGet - name: Setup NuGet
uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0 uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0
@@ -82,7 +85,7 @@ jobs:
- name: Set up MSBuild - name: Set up MSBuild
uses: microsoft/setup-msbuild@ede762b26a2de8d110bb5a3db4d7e0e080c0e917 # v1.3.3 uses: microsoft/setup-msbuild@ede762b26a2de8d110bb5a3db4d7e0e080c0e917 # v1.3.3
# This step might be obsolete at some point as .NET MAUI workloads # This step might be obsolete at some point as .NET MAUI workloads
# are starting to come pre-installed on the GH Actions build agents. # are starting to come pre-installed on the GH Actions build agents.
- name: Install MAUI Workload - name: Install MAUI Workload
run: dotnet workload install maui --ignore-failed-sources run: dotnet workload install maui --ignore-failed-sources
@@ -93,7 +96,8 @@ jobs:
- name: Install Microsoft OpenJDK 11 - name: Install Microsoft OpenJDK 11
run: | run: |
choco install microsoft-openjdk11 --no-progress choco install microsoft-openjdk11 --no-progress
Write-Output "JAVA_HOME=$(Get-ChildItem -Path 'C:\Program Files\Microsoft\jdk*' | Select -First 1 -ExpandProperty FullName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append Write-Output "JAVA_HOME=$(Get-ChildItem -Path 'C:\Program Files\Microsoft\jdk*' | `
Select -First 1 -ExpandProperty FullName)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
Write-Output "Java Home: $env:JAVA_HOME" Write-Output "Java Home: $env:JAVA_HOME"
- name: Print environment - name: Print environment
@@ -109,27 +113,34 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Decrypt secrets - name: Login to Azure - CI Subscription
env: uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} with:
run: | creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
mkdir -p ~/secrets
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - name: Download secrets
--output ./${{ env.main_app_folder_path }}/app_play-keystore.jks ./.github/secrets/app_play-keystore.jks.gpg env:
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ ACCOUNT_NAME: bitwardenci
--output ./${{ env.main_app_folder_path }}/app_upload-keystore.jks ./.github/secrets/app_upload-keystore.jks.gpg CONTAINER_NAME: mobile
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ run: |
--output $HOME/secrets/play_creds.json ./.github/secrets/play_creds.json.gpg mkdir -p $HOME/secrets
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
--name app_play-keystore.jks --file ./${{ env.android_folder_path_bash }}/app_play-keystore.jks --output none
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
--name app_upload-keystore.jks --file ./${{ env.android_folder_path_bash }}/app_upload-keystore.jks --output none
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
--name play_creds.json --file $HOME/secrets/play_creds.json --output none
shell: bash shell: bash
- name: Decrypt secrets - Google Services - name: Download secrets - Google Services
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
env: env:
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} ACCOUNT_NAME: bitwardenci
CONTAINER_NAME: mobile
run: | run: |
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
--output ./${{ env.android_folder_path }}/google-services.json ./.github/secrets/google-services.json.gpg --name google-services.json --file ./${{ env.android_folder_path_bash }}/google-services.json --output none
shell: bash shell: bash
- name: Increment version - name: Increment version
@@ -139,9 +150,9 @@ jobs:
echo "########################################" echo "########################################"
echo "##### Setting Version Code $BUILD_NUMBER" echo "##### Setting Version Code $BUILD_NUMBER"
echo "########################################" echo "########################################"
sed -i "s/android:versionCode=\"1\"/android:versionCode=\"$BUILD_NUMBER\"/" \ sed -i "s/android:versionCode=\"1\"/android:versionCode=\"$BUILD_NUMBER\"/" \
./${{ env.android_folder_path }}/AndroidManifest.xml ./${{ env.android_folder_path_bash }}/AndroidManifest.xml
shell: bash shell: bash
- name: Restore packages - name: Restore packages
@@ -150,83 +161,75 @@ jobs:
- name: Restore tools - name: Restore tools
run: dotnet tool restore run: dotnet tool restore
# - name: Verify Format # - name: Run Core tests
# run: dotnet tool run dotnet-format --check # run: |
# dotnet test test/Core.Test/Core.Test.csproj --logger "trx;LogFileName=test-results.trx" `
# /p:CustomConstants=UT
- name: Run Core tests # - name: Report test results
run: dotnet test test/Core.Test/Core.Test.csproj --logger "trx;LogFileName=test-results.trx" /p:CustomConstants=UT # uses: dorny/test-reporter@eaa763f6ffc21c7a37837f56cd5f9737f27fc6c8 # v1.8.0
# if: always()
- name: Report test results # with:
uses: dorny/test-reporter@eaa763f6ffc21c7a37837f56cd5f9737f27fc6c8 # v1.8.0 # name: Test Results
if: always() # path: "**/test-results.trx"
with: # reporter: dotnet-trx
name: Test Results # fail-on-error: true
path: "**/test-results.trx"
reporter: dotnet-trx
fail-on-error: true
- name: Build Play Store publisher - name: Build Play Store publisher
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
run: dotnet build ./store/google/Publisher/Publisher.csproj -p:Configuration=Release run: dotnet build .\store\google\Publisher\Publisher.csproj /p:Configuration=Release
- name: Setup Android build (${{ matrix.variant }}) - name: Setup Android build (${{ matrix.variant }})
run: dotnet cake build.cake --target Android --variant ${{ matrix.variant }} run: dotnet cake build.cake --target Android --variant ${{ matrix.variant }}
- name: Build Android - name: Build & Sign Android
run: |
$configuration = "Release";
$projToBuild = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_project_path }}");
Write-Output "########################################"
Write-Output "##### Build $configuration Configuration"
Write-Output "########################################"
dotnet build $projToBuild -c $configuration -f ${{ env.target-net-version }}-android
- name: Sign Android Build
env: env:
PLAY_KEYSTORE_PASSWORD: ${{ secrets.PLAY_KEYSTORE_PASSWORD }} PLAY_KEYSTORE_PASSWORD: ${{ secrets.PLAY_KEYSTORE_PASSWORD }}
UPLOAD_KEYSTORE_PASSWORD: ${{ secrets.UPLOAD_KEYSTORE_PASSWORD }} UPLOAD_KEYSTORE_PASSWORD: ${{ secrets.UPLOAD_KEYSTORE_PASSWORD }}
run: | run: |
$projToBuild = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_project_path }}"); $projToBuild = "$($env:GITHUB_WORKSPACE)/${{ env.main_app_project_path }}";
$packageName = "com.x8bit.bitwarden"; $packageName = "com.x8bit.bitwarden";
if ("${{ matrix.variant }}" -ne "prod") if ("${{ matrix.variant }}" -ne "prod")
{ {
$packageName = "com.x8bit.bitwarden.${{ matrix.variant }}"; $packageName = "com.x8bit.bitwarden.${{ matrix.variant }}";
} }
Write-Output "########################################"
Write-Output "##### Sign Google Play Bundle Release Configuration" Write-Output "##### Sign Google Play Bundle Release Configuration"
Write-Output "########################################"
dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android /p:AndroidPackageFormats=aab /p:AndroidKeyStore=true /p:AndroidSigningKeyStore=$("app_upload-keystore.jks") /p:AndroidSigningKeyAlias=upload /p:AndroidSigningKeyPass="$($env:UPLOAD_KEYSTORE_PASSWORD)" /p:AndroidSigningStorePass="$($env:UPLOAD_KEYSTORE_PASSWORD)" --no-restore $signingUploadKeyStore = "$($env:GITHUB_WORKSPACE)\${{ env.android_folder_path }}\app_upload-keystore.jks"
dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android `
/p:AndroidPackageFormats=aab `
/p:AndroidKeyStore=true `
/p:AndroidSigningKeyStore=$signingUploadKeyStore `
/p:AndroidSigningKeyAlias=upload `
/p:AndroidSigningKeyPass="$($env:UPLOAD_KEYSTORE_PASSWORD)" `
/p:AndroidSigningStorePass="$($env:UPLOAD_KEYSTORE_PASSWORD)" --no-restore
Write-Output "########################################"
Write-Output "##### Copy Google Play Bundle to project root" Write-Output "##### Copy Google Play Bundle to project root"
Write-Output "########################################"
$signedAabPath = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_folder_path }}/bin/Release/${{ env.target-net-version }}-android/publish/$($packageName)-Signed.aab"); $signedAabPath = "$($env:GITHUB_WORKSPACE)\${{ env.main_app_folder_path }}\bin\Release\${{ env.target-net-version }}-android\publish\$($packageName)-Signed.aab";
$signedAabDestPath = $($env:GITHUB_WORKSPACE + "/$($packageName).aab"); $signedAabDestPath = "$($env:GITHUB_WORKSPACE)\$($packageName).aab";
Copy-Item $signedAabPath $signedAabDestPath Copy-Item $signedAabPath $signedAabDestPath
Write-Output "########################################"
Write-Output "##### Sign APK Release Configuration" Write-Output "##### Sign APK Release Configuration"
Write-Output "########################################"
dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android /p:AndroidKeyStore=true /p:AndroidSigningKeyStore=$("app_play-keystore.jks") /p:AndroidSigningKeyAlias=bitwarden /p:AndroidSigningKeyPass="$($env:PLAY_KEYSTORE_PASSWORD)" /p:AndroidSigningStorePass="$($env:PLAY_KEYSTORE_PASSWORD)" --no-restore $signingPlayKeyStore = "$($env:GITHUB_WORKSPACE)\${{ env.android_folder_path }}\app_play-keystore.jks"
dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android `
/p:AndroidKeyStore=true `
/p:AndroidSigningKeyStore=$signingPlayKeyStore `
/p:AndroidSigningKeyAlias=bitwarden `
/p:AndroidSigningKeyPass="$($env:PLAY_KEYSTORE_PASSWORD)" `
/p:AndroidSigningStorePass="$($env:PLAY_KEYSTORE_PASSWORD)" --no-restore
Write-Output "########################################"
Write-Output "##### Copy Release APK to project root" Write-Output "##### Copy Release APK to project root"
Write-Output "########################################"
$signedApkPath = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_folder_path }}/bin/Release/${{ env.target-net-version }}-android/publish/$($packageName)-Signed.apk");
$signedApkDestPath = $($env:GITHUB_WORKSPACE + "/$($packageName).apk");
$signedApkPath = "$($env:GITHUB_WORKSPACE)\${{ env.main_app_folder_path }}\bin\Release\${{ env.target-net-version }}-android\publish\$($packageName)-Signed.apk";
$signedApkDestPath = "$($env:GITHUB_WORKSPACE)\$($packageName).apk";
Copy-Item $signedApkPath $signedApkDestPath Copy-Item $signedApkPath $signedApkDestPath
- name: Upload Prod .aab artifact - name: Upload Prod .aab artifact
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: com.x8bit.bitwarden.aab name: com.x8bit.bitwarden.aab
path: ./com.x8bit.bitwarden.aab path: ./com.x8bit.bitwarden.aab
@@ -234,7 +237,7 @@ jobs:
- name: Upload Prod .apk artifact - name: Upload Prod .apk artifact
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: com.x8bit.bitwarden.apk name: com.x8bit.bitwarden.apk
path: ./com.x8bit.bitwarden.apk path: ./com.x8bit.bitwarden.apk
@@ -242,7 +245,7 @@ jobs:
- name: Upload Other .apk artifact - name: Upload Other .apk artifact
if: ${{ matrix.variant != 'prod' }} if: ${{ matrix.variant != 'prod' }}
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: com.x8bit.bitwarden.${{ matrix.variant }}.apk name: com.x8bit.bitwarden.${{ matrix.variant }}.apk
path: ./com.x8bit.bitwarden.${{ matrix.variant }}.apk path: ./com.x8bit.bitwarden.${{ matrix.variant }}.apk
@@ -262,7 +265,7 @@ jobs:
- name: Upload .apk sha file for prod - name: Upload .apk sha file for prod
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bw-android-apk-sha256.txt name: bw-android-apk-sha256.txt
path: ./bw-android-apk-sha256.txt path: ./bw-android-apk-sha256.txt
@@ -270,7 +273,7 @@ jobs:
- name: Upload .apk sha file for other - name: Upload .apk sha file for other
if: ${{ matrix.variant != 'prod' }} if: ${{ matrix.variant != 'prod' }}
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bw-android-${{ matrix.variant }}-apk-sha256.txt name: bw-android-${{ matrix.variant }}-apk-sha256.txt
path: ./bw-android-${{ matrix.variant }}-apk-sha256.txt path: ./bw-android-${{ matrix.variant }}-apk-sha256.txt
@@ -283,20 +286,20 @@ jobs:
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0) || (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|| github.ref == 'refs/heads/hotfix-rc' ) }} || github.ref == 'refs/heads/hotfix-rc' ) }}
run: | run: |
PUBLISHER_PATH="$GITHUB_WORKSPACE/store/google/Publisher/bin/Release/net7.0/Publisher.dll" $publisherPath = "$($env:GITHUB_WORKSPACE)\store\google\Publisher\bin\Release\net8.0\Publisher.dll"
CREDS_PATH="$HOME/secrets/play_creds.json" $credsPath = "$($HOME)\secrets\play_creds.json"
AAB_PATH="$GITHUB_WORKSPACE/com.x8bit.bitwarden.aab" $aabPath = "$($env:GITHUB_WORKSPACE)\com.x8bit.bitwarden.aab"
TRACK="internal" $track = "internal"
dotnet $PUBLISHER_PATH $CREDS_PATH $AAB_PATH $TRACK dotnet $publisherPath $credsPath $aabPath $track
shell: bash
f-droid: f-droid:
name: F-Droid Build name: F-Droid Build
runs-on: windows-2022 runs-on: windows-2022
env: env:
android_folder_path: src/App/Platforms/Android android_folder_path: src\App\Platforms\Android
android_folder_path_bash: src/App/Platforms/Android
android_manifest_path: src/App/Platforms/Android/AndroidManifest.xml android_manifest_path: src/App/Platforms/Android/AndroidManifest.xml
steps: steps:
- name: Setup NuGet - name: Setup NuGet
@@ -312,7 +315,7 @@ jobs:
- name: Set up MSBuild - name: Set up MSBuild
uses: microsoft/setup-msbuild@ede762b26a2de8d110bb5a3db4d7e0e080c0e917 # v1.3.3 uses: microsoft/setup-msbuild@ede762b26a2de8d110bb5a3db4d7e0e080c0e917 # v1.3.3
# This step might be obsolete at some point as .NET MAUI workloads # This step might be obsolete at some point as .NET MAUI workloads
# are starting to come pre-installed on the GH Actions build agents. # are starting to come pre-installed on the GH Actions build agents.
- name: Install MAUI Workload - name: Install MAUI Workload
run: dotnet workload install maui --ignore-failed-sources run: dotnet workload install maui --ignore-failed-sources
@@ -337,23 +340,25 @@ jobs:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Decrypt secrets - name: Login to Azure - CI Subscription
env: uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} with:
run: | creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
mkdir -p ~/secrets
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - name: Download secrets
--output ./${{ env.main_app_folder_path }}/app_fdroid-keystore.jks ./.github/secrets/app_fdroid-keystore.jks.gpg env:
ACCOUNT_NAME: bitwardenci
CONTAINER_NAME: mobile
FILE: app_fdroid-keystore.jks
run: |
az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $FILE \
--file ${{ env.android_folder_path_bash }}/$FILE --output none
shell: bash shell: bash
- name: Increment version - name: Increment version
run: | run: |
BUILD_NUMBER=$((3000 + $GITHUB_RUN_NUMBER)) BUILD_NUMBER=$((3000 + $GITHUB_RUN_NUMBER))
echo "########################################"
echo "##### Setting Version Code $BUILD_NUMBER" echo "##### Setting Version Code $BUILD_NUMBER"
echo "########################################"
sed -i "s/android:versionCode=\"1\"/android:versionCode=\"$BUILD_NUMBER\"/" \ sed -i "s/android:versionCode=\"1\"/android:versionCode=\"$BUILD_NUMBER\"/" \
./${{ env.android_manifest_path }} ./${{ env.android_manifest_path }}
@@ -366,16 +371,12 @@ jobs:
$androidManifest = $($env:GITHUB_WORKSPACE + "/${{ env.android_manifest_path }}"); $androidManifest = $($env:GITHUB_WORKSPACE + "/${{ env.android_manifest_path }}");
Write-Output "########################################" Write-Output "##### Back up project files"
Write-Output "##### Backup project files"
Write-Output "########################################"
Copy-Item $androidManifest $($androidManifest + ".original"); Copy-Item $androidManifest $($androidManifest + ".original");
Copy-Item $appPath $($appPath + ".original"); Copy-Item $appPath $($appPath + ".original");
Write-Output "########################################"
Write-Output "##### Cleanup Android Manifest" Write-Output "##### Cleanup Android Manifest"
Write-Output "########################################"
$xml=New-Object XML; $xml=New-Object XML;
$xml.Load($androidManifest); $xml.Load($androidManifest);
@@ -388,41 +389,33 @@ jobs:
- name: Restore packages - name: Restore packages
run: dotnet restore run: dotnet restore
- name: Build for F-Droid - name: Build & Sign F-Droid
run: |
$configuration = "Release";
$projToBuild = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_project_path }}");
Write-Output "########################################"
Write-Output "##### Build $configuration FDROID
Write-Output "########################################"
dotnet build $projToBuild -c $configuration -f ${{ env.target-net-version }}-android /p:CustomConstants="FDROID"
- name: Sign for F-Droid
env: env:
FDROID_KEYSTORE_PASSWORD: ${{ secrets.FDROID_KEYSTORE_PASSWORD }} FDROID_KEYSTORE_PASSWORD: ${{ secrets.FDROID_KEYSTORE_PASSWORD }}
run: | run: |
$projToBuild = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_project_path }}"); $projToBuild = "$($env:GITHUB_WORKSPACE)\${{ env.main_app_project_path }}";
$packageName = "com.x8bit.bitwarden"; $packageName = "com.x8bit.bitwarden";
Write-Output "########################################"
Write-Output "##### Sign FDroid" Write-Output "##### Sign FDroid"
Write-Output "########################################"
dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android /p:AndroidKeyStore=true /p:AndroidSigningKeyStore=$("app_fdroid-keystore.jks") /p:AndroidSigningKeyAlias=bitwarden /p:AndroidSigningKeyPass="$($env:FDROID_KEYSTORE_PASSWORD)" /p:AndroidSigningStorePass="$($env:FDROID_KEYSTORE_PASSWORD)" /p:CustomConstants="FDROID" --no-restore $signingFdroidKeyStore = "$($env:GITHUB_WORKSPACE)\${{ env.android_folder_path }}\app_fdroid-keystore.jks"
dotnet publish $projToBuild -c Release -f ${{ env.target-net-version }}-android `
/p:AndroidKeyStore=true `
/p:AndroidSigningKeyStore=$signingFdroidKeyStore `
/p:AndroidSigningKeyAlias=bitwarden `
/p:AndroidSigningKeyPass="$($env:FDROID_KEYSTORE_PASSWORD)" `
/p:AndroidSigningStorePass="$($env:FDROID_KEYSTORE_PASSWORD)" `
/p:CustomConstants="FDROID" --no-restore
Write-Output "########################################"
Write-Output "##### Copy FDroid apk to project root" Write-Output "##### Copy FDroid apk to project root"
Write-Output "########################################"
$signedApkPath = $($env:GITHUB_WORKSPACE + "/${{ env.main_app_folder_path }}/bin/Release/${{ env.target-net-version }}-android/publish/$($packageName)-Signed.apk"); $signedApkPath = "$($env:GITHUB_WORKSPACE)\${{ env.main_app_folder_path }}\bin\Release\${{ env.target-net-version }}-android\publish\$($packageName)-Signed.apk";
$signedApkDestPath = $($env:GITHUB_WORKSPACE + "/com.x8bit.bitwarden-fdroid.apk"); $signedApkDestPath = "$($env:GITHUB_WORKSPACE)\com.x8bit.bitwarden-fdroid.apk";
Copy-Item $signedApkPath $signedApkDestPath Copy-Item $signedApkPath $signedApkDestPath
- name: Upload F-Droid .apk artifact - name: Upload F-Droid .apk artifact
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: com.x8bit.bitwarden-fdroid.apk name: com.x8bit.bitwarden-fdroid.apk
path: ./com.x8bit.bitwarden-fdroid.apk path: ./com.x8bit.bitwarden-fdroid.apk
@@ -434,12 +427,13 @@ jobs:
-t sha256 | Out-File -Encoding ASCII ./bw-fdroid-apk-sha256.txt -t sha256 | Out-File -Encoding ASCII ./bw-fdroid-apk-sha256.txt
- name: Upload F-Droid sha file - name: Upload F-Droid sha file
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: bw-fdroid-apk-sha256.txt name: bw-fdroid-apk-sha256.txt
path: ./bw-fdroid-apk-sha256.txt path: ./bw-fdroid-apk-sha256.txt
if-no-files-found: error if-no-files-found: error
ios: ios:
name: Apple iOS name: Apple iOS
runs-on: macos-13 runs-on: macos-13
@@ -458,13 +452,13 @@ jobs:
uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0 uses: nuget/setup-nuget@296fd3ccf8528660c91106efefe2364482f86d6f # v1.2.0
with: with:
nuget-version: 6.4.0 nuget-version: 6.4.0
- name: Set up .NET - name: Set up .NET
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0 uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0
with: with:
dotnet-version: '8.0.x' dotnet-version: '8.0.x'
# This step might be obsolete at some point as .NET MAUI workloads # This step might be obsolete at some point as .NET MAUI workloads
# are starting to come pre-installed on the GH Actions build agents. # are starting to come pre-installed on the GH Actions build agents.
- name: Install MAUI Workload - name: Install MAUI Workload
run: dotnet workload install maui --ignore-failed-sources run: dotnet workload install maui --ignore-failed-sources
@@ -493,42 +487,42 @@ jobs:
keyvault: "bitwarden-ci" keyvault: "bitwarden-ci"
secrets: "appcenter-ios-token" secrets: "appcenter-ios-token"
- name: Decrypt secrets - name: Download Provisioning Profiles secrets
env: env:
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} ACCOUNT_NAME: bitwardenci
CONTAINER_NAME: profiles
run: | run: |
mkdir -p ~/secrets mkdir -p $HOME/secrets
profiles=(
"dist_autofill.mobileprovision"
"dist_bitwarden.mobileprovision"
"dist_extension.mobileprovision"
"dist_share_extension.mobileprovision"
"dist_bitwarden_watch_app.mobileprovision"
"dist_bitwarden_watch_app_extension.mobileprovision"
)
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ for FILE in "${profiles[@]}"
--output $HOME/secrets/bitwarden-mobile-key.p12 ./.github/secrets/bitwarden-mobile-key.p12.gpg do
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $FILE \
--output $HOME/secrets/iphone-distribution-cert.p12 ./.github/secrets/iphone-distribution-cert.p12.gpg --file $HOME/secrets/$FILE --output none
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ done
--output $HOME/secrets/dist_autofill.mobileprovision ./.github/secrets/dist_autofill.mobileprovision.gpg
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ - name: Download Google Services secret
--output $HOME/secrets/dist_bitwarden.mobileprovision ./.github/secrets/dist_bitwarden.mobileprovision.gpg env:
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ ACCOUNT_NAME: bitwardenci
--output $HOME/secrets/dist_extension.mobileprovision ./.github/secrets/dist_extension.mobileprovision.gpg CONTAINER_NAME: mobile
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ FILE: GoogleService-Info.plist
--output $HOME/secrets/dist_share_extension.mobileprovision \ run: |
./.github/secrets/dist_share_extension.mobileprovision.gpg mkdir -p $HOME/secrets
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME --name $FILE \
--output $HOME/secrets/dist_watch_app.mobileprovision \ --file src/watchOS/bitwarden/$FILE --output none
./.github/secrets/dist_watch_app.mobileprovision.gpg
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output $HOME/secrets/dist_watch_app_extension.mobileprovision \
./.github/secrets/dist_watch_app_extension.mobileprovision.gpg
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output ./src/watchOS/bitwarden/GoogleService-Info.plist ./.github/secrets/GoogleService-Info.plist.gpg
- name: Increment version - name: Increment version
run: | run: |
BUILD_NUMBER=$((100 + $GITHUB_RUN_NUMBER)) BUILD_NUMBER=$((100 + $GITHUB_RUN_NUMBER))
echo "########################################"
echo "##### Setting CFBundleVersion $BUILD_NUMBER" echo "##### Setting CFBundleVersion $BUILD_NUMBER"
echo "########################################"
echo "### CFBundleVersion $BUILD_NUMBER" >> $GITHUB_STEP_SUMMARY echo "### CFBundleVersion $BUILD_NUMBER" >> $GITHUB_STEP_SUMMARY
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./${{ env.ios_folder_path }}/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./${{ env.ios_folder_path }}/Info.plist
@@ -536,30 +530,30 @@ jobs:
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Autofill/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Autofill/Info.plist
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.ShareExtension/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.ShareExtension/Info.plist
cd src/watchOS/bitwarden cd src/watchOS/bitwarden
agvtool new-version -all $BUILD_NUMBER agvtool new-version -all $BUILD_NUMBER
- name: Update Entitlements - name: Update Entitlements
run: | run: |
echo "########################################"
echo "##### Updating Entitlements" echo "##### Updating Entitlements"
echo "########################################"
perl -0777 -pi.bak -e 's/<key>aps-environment<\/key>\s*<string>development<\/string>/<key>aps-environment<\/key>\n\t<string>production<\/string>/' ./${{ env.ios_folder_path }}/Entitlements.plist perl -0777 -pi.bak -e 's/<key>aps-environment<\/key>\s*<string>development<\/string>/<key>aps-environment<\/key>\n\t<string>production<\/string>/' ./${{ env.ios_folder_path }}/Entitlements.plist
- name: Get certificates
run: |
mkdir -p $HOME/certificates
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/ios-distribution |
jq -r .value | base64 -d > $HOME/certificates/ios-distribution.p12
- name: Set up Keychain - name: Set up Keychain
env: env:
KEYCHAIN_PASSWORD: ${{ secrets.IOS_KEYCHAIN_PASSWORD }} KEYCHAIN_PASSWORD: ${{ secrets.IOS_KEYCHAIN_PASSWORD }}
MOBILE_KEY_PASSWORD: ${{ secrets.IOS_KEY_PASSWORD }}
DIST_CERT_PASSWORD: ${{ secrets.IOS_DIST_CERT_PASSWORD }}
run: | run: |
security create-keychain -p $KEYCHAIN_PASSWORD build.keychain security create-keychain -p $KEYCHAIN_PASSWORD build.keychain
security default-keychain -s build.keychain security default-keychain -s build.keychain
security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain
security set-keychain-settings -lut 1200 build.keychain security set-keychain-settings -lut 1200 build.keychain
security import ~/secrets/bitwarden-mobile-key.p12 -k build.keychain -P $MOBILE_KEY_PASSWORD \
-T /usr/bin/codesign -T /usr/bin/security security import $HOME/certificates/ios-distribution.p12 -k build.keychain -P "" -T /usr/bin/codesign \
security import ~/secrets/iphone-distribution-cert.p12 -k build.keychain -P $DIST_CERT_PASSWORD \ -T /usr/bin/security
-T /usr/bin/codesign -T /usr/bin/security
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain
- name: Set up provisioning profiles - name: Set up provisioning profiles
@@ -568,8 +562,8 @@ jobs:
BITWARDEN_PROFILE_PATH=$HOME/secrets/dist_bitwarden.mobileprovision BITWARDEN_PROFILE_PATH=$HOME/secrets/dist_bitwarden.mobileprovision
EXTENSION_PROFILE_PATH=$HOME/secrets/dist_extension.mobileprovision EXTENSION_PROFILE_PATH=$HOME/secrets/dist_extension.mobileprovision
SHARE_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_share_extension.mobileprovision SHARE_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_share_extension.mobileprovision
WATCH_APP_PROFILE_PATH=$HOME/secrets/dist_watch_app.mobileprovision WATCH_APP_PROFILE_PATH=$HOME/secrets/dist_bitwarden_watch_app.mobileprovision
WATCH_APP_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_watch_app_extension.mobileprovision WATCH_APP_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_bitwarden_watch_app_extension.mobileprovision
PROFILES_DIR_PATH=$HOME/Library/MobileDevice/Provisioning\ Profiles PROFILES_DIR_PATH=$HOME/Library/MobileDevice/Provisioning\ Profiles
mkdir -p "$PROFILES_DIR_PATH" mkdir -p "$PROFILES_DIR_PATH"
@@ -597,74 +591,50 @@ jobs:
- name: Bulid WatchApp - name: Bulid WatchApp
run: | run: |
echo "########################################"
echo "##### Build WatchApp with Release Configuration" echo "##### Build WatchApp with Release Configuration"
echo "########################################"
xcodebuild archive -workspace ./src/watchOS/bitwarden/bitwarden.xcodeproj/project.xcworkspace -configuration Release -scheme bitwarden\ WatchKit\ App -archivePath ./src/watchOS/bitwarden xcodebuild archive -workspace ./src/watchOS/bitwarden/bitwarden.xcodeproj/project.xcworkspace -configuration Release -scheme bitwarden\ WatchKit\ App -archivePath ./src/watchOS/bitwarden
echo "########################################"
echo "##### Done"
echo "########################################"
- name: Archive Build for App Store - name: Archive Build for App Store
run: | run: |
Write-Output "########################################" echo "##### Archive for Release ios-arm64"
Write-Output "##### Archive for Release ios-arm64
Write-Output "########################################"
dotnet publish ${{ env.main_app_project_path }} -c Release -f ${{ env.target-net-version }}-ios /p:RuntimeIdentifier=ios-arm64 /p:ArchiveOnBuild=true /p:MtouchUseLlvm=false dotnet publish ${{ env.main_app_project_path }} -c Release -f ${{ env.target-net-version }}-ios /p:RuntimeIdentifier=ios-arm64 /p:ArchiveOnBuild=true /p:MtouchUseLlvm=false
Write-Output "########################################"
Write-Output "##### Done"
Write-Output "########################################"
shell: pwsh
- name: Archive Build for Mobile Automation - name: Archive Build for Mobile Automation
run: | run: |
Write-Output "########################################" echo "##### Archive Debug for iossimulator-x64"
Write-Output "##### Archive Debug for iossimulator-x64
Write-Output "########################################"
dotnet build ${{ env.main_app_project_path }} -c Debug -f ${{ env.target-net-version }}-ios /p:RuntimeIdentifier=iossimulator-x64 /p:ArchiveOnBuild=true /p:MtouchUseLlvm=false dotnet build ${{ env.main_app_project_path }} -c Debug -f ${{ env.target-net-version }}-ios /p:RuntimeIdentifier=iossimulator-x64 /p:ArchiveOnBuild=true /p:MtouchUseLlvm=false
ls $HOME/Library/Developer/Xcode/Archives
Write-Output "########################################"
Write-Output "##### Done"
Write-Output "########################################"
ls ~/Library/Developer/Xcode/Archives
shell: pwsh
- name: Export .ipa for App Store - name: Export .ipa for App Store
env:
EXPORT_OPTIONS_PATH: ./.github/resources/export-options-app-store.plist
EXPORT_PATH: ./bitwarden-export
run: | run: |
EXPORT_OPTIONS_PATH="./.github/resources/export-options-app-store.plist"
ARCHIVE_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive" ARCHIVE_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive"
EXPORT_PATH="./bitwarden-export"
xcodebuild -exportArchive -archivePath $ARCHIVE_PATH -exportPath $EXPORT_PATH \ xcodebuild -exportArchive -archivePath $ARCHIVE_PATH -exportPath $EXPORT_PATH \
-exportOptionsPlist $EXPORT_OPTIONS_PATH -exportOptionsPlist $EXPORT_OPTIONS_PATH
- name: Export .app for Automation CI - name: Export .app for Automation CI
env:
ARCHIVE_PATH: ./${{ env.main_app_folder_path }}/bin/Debug/${{ env.target-net-version }}-ios/iossimulator-x64
EXPORT_PATH: ./bitwarden-export
run: | run: |
ARCHIVE_PATH="./${{ env.main_app_folder_path }}/bin/Debug/${{ env.target-net-version }}-ios/iossimulator-x64"
EXPORT_PATH="./bitwarden-export"
zip -r -q ${{ env.app_ci_output_filename }}.app.zip $ARCHIVE_PATH zip -r -q ${{ env.app_ci_output_filename }}.app.zip $ARCHIVE_PATH
mv ${{ env.app_ci_output_filename }}.app.zip $EXPORT_PATH mv ${{ env.app_ci_output_filename }}.app.zip $EXPORT_PATH
- name: Copy all dSYMs files to upload - name: Copy all dSYMs files to upload
env:
EXPORT_PATH: ./bitwarden-export
WATCH_ARCHIVE_DSYMS_PATH: ./src/watchOS/bitwarden.xcarchive/dSYMs/
WATCH_DSYMS_EXPORT_PATH: ./bitwarden-export/Watch_dSYMs
run: | run: |
ARCHIVE_DSYMS_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive/dSYMs" ARCHIVE_DSYMS_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive/dSYMs"
EXPORT_PATH="./bitwarden-export"
WATCH_ARCHIVE_DSYMS_PATH="./src/watchOS/bitwarden.xcarchive/dSYMs/"
WATCH_DSYMS_EXPORT_PATH="$EXPORT_PATH/Watch_dSYMs"
cp -r -v $ARCHIVE_DSYMS_PATH $EXPORT_PATH cp -r -v $ARCHIVE_DSYMS_PATH $EXPORT_PATH
mkdir $WATCH_DSYMS_EXPORT_PATH mkdir $WATCH_DSYMS_EXPORT_PATH
cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH
- name: Upload App Store .ipa & dSYMs artifacts - name: Upload App Store .ipa & dSYMs artifacts
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: Bitwarden iOS name: Bitwarden iOS
path: | path: |
@@ -673,7 +643,7 @@ jobs:
if-no-files-found: error if-no-files-found: error
- name: Upload .app file for Automation CI - name: Upload .app file for Automation CI
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
with: with:
name: ${{ env.app_ci_output_filename }}.app.zip name: ${{ env.app_ci_output_filename }}.app.zip
path: ./bitwarden-export/${{ env.app_ci_output_filename }}.app.zip path: ./bitwarden-export/${{ env.app_ci_output_filename }}.app.zip
@@ -707,10 +677,7 @@ jobs:
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0) || (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|| github.ref == 'refs/heads/hotfix-rc' || github.ref == 'refs/heads/hotfix-rc'
run: | run: |
echo "########################################"
echo "##### Uploading Watch dSYMs to Firebase" echo "##### Uploading Watch dSYMs to Firebase"
echo "########################################"
find "$HOME/Library/Developer/XCode/DerivedData" -name "upload-symbols" -exec chmod +x {} \; -exec {} -gsp "./src/watchOS/bitwarden/GoogleService-Info.plist" -p ios "./bitwarden-export/Watch_dSYMs" \; find "$HOME/Library/Developer/XCode/DerivedData" -name "upload-symbols" -exec chmod +x {} \; -exec {} -gsp "./src/watchOS/bitwarden/GoogleService-Info.plist" -p ios "./bitwarden-export/Watch_dSYMs" \;
- name: Validate app in App Store - name: Validate app in App Store
@@ -726,7 +693,6 @@ jobs:
run: | run: |
xcrun altool --validate-app --type ios --file "./bitwarden-export/Bitwarden.ipa" \ xcrun altool --validate-app --type ios --file "./bitwarden-export/Bitwarden.ipa" \
--username "$APPLE_ID_USERNAME" --password "$APPLE_ID_PASSWORD" --username "$APPLE_ID_USERNAME" --password "$APPLE_ID_PASSWORD"
shell: bash
- name: Deploy to App Store - name: Deploy to App Store
if: | if: |
@@ -770,13 +736,13 @@ jobs:
secrets: "crowdin-api-token" secrets: "crowdin-api-token"
- name: Upload Sources - name: Upload Sources
uses: crowdin/github-action@97bef4fd3f1b853eb105bc99b8d0d563760e024c # v1.17.0 uses: crowdin/github-action@c953b17499daa6be3e5afbf7a63616fb02d8b18d # v1.19.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
with: with:
config: crowdin.yml config: crowdin.yml
crowdin_branch_name: main crowdin_branch_name: main
upload_sources: true upload_sources: true
upload_translations: false upload_translations: false
@@ -794,27 +760,11 @@ jobs:
steps: steps:
- name: Check if any job failed - name: Check if any job failed
if: | if: |
(github.ref == 'refs/heads/main') (github.ref == 'refs/heads/main'
|| (github.ref == 'refs/heads/rc') || github.ref == 'refs/heads/rc'
|| (github.ref == 'refs/heads/hotfix-rc') || github.ref == 'refs/heads/hotfix-rc')
env: && contains(needs.*.result, 'failure')
CLOC_STATUS: ${{ needs.cloc.result }} run: exit 1
ANDROID_STATUS: ${{ needs.android.result }}
F_DROID_STATUS: ${{ needs.f-droid.result }}
IOS_STATUS: ${{ needs.ios.result }}
CROWDIN_PUSH_STATUS: ${{ needs.crowdin-push.result }}
run: |
if [ "$CLOC_STATUS" = "failure" ]; then
exit 1
elif [ "$ANDROID_STATUS" = "failure" ]; then
exit 1
elif [ "$F_DROID_STATUS" = "failure" ]; then
exit 1
elif [ "$IOS_STATUS" = "failure" ]; then
exit 1
elif [ "$CROWDIN_PUSH_STATUS" = "failure" ]; then
exit 1
fi
- name: Login to Azure - CI Subscription - name: Login to Azure - CI Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0

View File

@@ -30,7 +30,7 @@ jobs:
secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase" secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase"
- name: Download translations - name: Download translations
uses: crowdin/github-action@97bef4fd3f1b853eb105bc99b8d0d563760e024c # v1.17.0 uses: crowdin/github-action@c953b17499daa6be3e5afbf7a63616fb02d8b18d # v1.19.0
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}

View File

@@ -28,7 +28,7 @@ jobs:
branch-name: ${{ steps.branch.outputs.branch-name }} branch-name: ${{ steps.branch.outputs.branch-name }}
steps: steps:
- name: Branch check - name: Branch check
if: github.event.inputs.release_type != 'Dry Run' if: inputs.release_type != 'Dry Run'
run: | run: |
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then
echo "===================================" echo "==================================="
@@ -44,9 +44,9 @@ jobs:
id: version id: version
uses: bitwarden/gh-actions/release-version-check@main uses: bitwarden/gh-actions/release-version-check@main
with: with:
release-type: ${{ github.event.inputs.release_type }} release-type: ${{ inputs.release_type }}
project-type: xamarin project-type: xamarin
file: src/Android/Properties/AndroidManifest.xml file: src/App/Platforms/Android/AndroidManifest.xml
- name: Get branch name - name: Get branch name
id: branch id: branch
@@ -55,8 +55,8 @@ jobs:
echo "branch-name=$BRANCH_NAME" >> $GITHUB_OUTPUT echo "branch-name=$BRANCH_NAME" >> $GITHUB_OUTPUT
- name: Create GitHub deployment - name: Create GitHub deployment
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ inputs.release_type != 'Dry Run' }}
uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5 uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7
id: deployment id: deployment
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
@@ -67,16 +67,16 @@ jobs:
- name: Download all artifacts - name: Download all artifacts
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ inputs.release_type != 'Dry Run' }}
uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d # v3.0.0 uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
branch: ${{ steps.branch.outputs.branch-name }} branch: ${{ steps.branch.outputs.branch-name }}
- name: Dry Run - Download all artifacts - name: Dry Run - Download all artifacts
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ inputs.release_type == 'Dry Run' }}
uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d # v3.0.0 uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
@@ -86,8 +86,8 @@ jobs:
run: zip -r Bitwarden\ iOS.zip Bitwarden\ iOS run: zip -r Bitwarden\ iOS.zip Bitwarden\ iOS
- name: Create release - name: Create release
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@6c75be85e571768fa31b40abf38de58ba0397db5 # v1.13.0 uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
with: with:
artifacts: "./com.x8bit.bitwarden.aab/com.x8bit.bitwarden.aab, artifacts: "./com.x8bit.bitwarden.aab/com.x8bit.bitwarden.aab,
./com.x8bit.bitwarden.apk/com.x8bit.bitwarden.apk, ./com.x8bit.bitwarden.apk/com.x8bit.bitwarden.apk,
@@ -103,16 +103,16 @@ jobs:
draft: true draft: true
- name: Update deployment status to Success - name: Update deployment status to Success
if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }} if: ${{ inputs.release_type != 'Dry Run' && success() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
state: 'success' state: 'success'
deployment-id: ${{ steps.deployment.outputs.deployment_id }} deployment-id: ${{ steps.deployment.outputs.deployment_id }}
- name: Update deployment status to Failure - name: Update deployment status to Failure
if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }} if: ${{ inputs.release_type != 'Dry Run' && failure() }}
uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 uses: chrnorm/deployment-status@9a72af4586197112e0491ea843682b5dc280d806 # v2.0.3
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
state: 'failure' state: 'failure'
@@ -129,8 +129,8 @@ jobs:
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- name: Download F-Droid .apk artifact - name: Download F-Droid .apk artifact
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ inputs.release_type != 'Dry Run' }}
uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d # v3.0.0 uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
@@ -138,8 +138,8 @@ jobs:
name: com.x8bit.bitwarden-fdroid.apk name: com.x8bit.bitwarden-fdroid.apk
- name: Dry Run - Download F-Droid .apk artifact - name: Dry Run - Download F-Droid .apk artifact
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ inputs.release_type == 'Dry Run' }}
uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d # v3.0.0 uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
with: with:
workflow: build.yml workflow: build.yml
workflow_conclusion: success workflow_conclusion: success
@@ -147,7 +147,7 @@ jobs:
name: com.x8bit.bitwarden-fdroid.apk name: com.x8bit.bitwarden-fdroid.apk
- name: Set up Node - name: Set up Node
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with: with:
node-version: '16.x' node-version: '16.x'
@@ -176,13 +176,19 @@ jobs:
- name: Install Node dependencies - name: Install Node dependencies
run: npm install run: npm install
- name: Decrypt secrets - name: Login to Azure - CI Subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Download secrets
env: env:
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} ACCOUNT_NAME: bitwardenci
CONTAINER_NAME: mobile
run: | run: |
mkdir -p ~/secrets mkdir -p $HOME/secrets
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ az storage blob download --account-name $ACCOUNT_NAME --container-name $CONTAINER_NAME \
--output ./store/fdroid/keystore.jks ./.github/secrets/store_fdroid-keystore.jks.gpg --name store_fdroid-keystore.jks --file ./store/fdroid/keystore.jks --output none
- name: Compile for F-Droid Store - name: Compile for F-Droid Store
env: env:
@@ -211,5 +217,5 @@ jobs:
cd $GITHUB_WORKSPACE cd $GITHUB_WORKSPACE
- name: Deploy to gh-pages - name: Deploy to gh-pages
if: ${{ github.event.inputs.release_type != 'Dry Run' }} if: ${{ inputs.release_type != 'Dry Run' }}
run: npm run deploy run: npm run deploy

View File

@@ -191,21 +191,27 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with: with:
ref: main ref: main
- name: Install xmllint
run: sudo apt install -y libxml2-utils
- name: Verify version has been updated - name: Verify version has been updated
env: env:
NEW_VERSION: ${{ inputs.version_number }} NEW_VERSION: ${{ inputs.version_number }}
run: | run: |
# Wait for version to change. # Wait for version to change.
do while : ; do
echo "Waiting for version to be updated..." echo "Waiting for version to be updated..."
git pull --force git pull --force
CURRENT_VERSION=$(xmllint --xpath ' CURRENT_VERSION=$(xmllint --xpath '
string(/manifest/@*[local-name()="versionName" string(/manifest/@*[local-name()="versionName"
and namespace-uri()="http://schemas.android.com/apk/res/android"]) and namespace-uri()="http://schemas.android.com/apk/res/android"])
' src/App/Platforms/Android/AndroidManifest.xml) ' src/App/Platforms/Android/AndroidManifest.xml)
# If the versions don't match we continue the loop, otherwise we break out of the loop.
[[ "$NEW_VERSION" != "$CURRENT_VERSION" ]] || break
sleep 10 sleep 10
done while [[ "$NEW_VERSION" != "$CURRENT_VERSION" ]] done
- name: Cut RC branch - name: Cut RC branch
run: | run: |

View File

@@ -1,11 +0,0 @@
---
name: Workflow Linter
on:
pull_request:
paths:
- .github/workflows/**
jobs:
call-workflow:
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@main

View File

@@ -1,6 +1,6 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<MauiVersion>8.0.4-nightly.*</MauiVersion> <MauiVersion>8.0.7</MauiVersion>
<ReleaseCodesignProvision>Automatic:AppStore</ReleaseCodesignProvision> <ReleaseCodesignProvision>Automatic:AppStore</ReleaseCodesignProvision>
<ReleaseCodesignKey>iPhone Distribution</ReleaseCodesignKey> <ReleaseCodesignKey>iPhone Distribution</ReleaseCodesignKey>
<IncludeBitwardeniOSExtensions>True</IncludeBitwardeniOSExtensions> <IncludeBitwardeniOSExtensions>True</IncludeBitwardeniOSExtensions>
@@ -10,4 +10,4 @@
<!-- Uncomment this when Unit Testing--> <!-- Uncomment this when Unit Testing-->
<!-- <CustomConstants>UT</CustomConstants> --> <!-- <CustomConstants>UT</CustomConstants> -->
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@@ -2,9 +2,9 @@ project_id_env: _CROWDIN_PROJECT_ID
api_token_env: CROWDIN_API_TOKEN api_token_env: CROWDIN_API_TOKEN
preserve_hierarchy: true preserve_hierarchy: true
files: files:
- source: /src/App/Resources/AppResources.resx - source: /src/Core/Resources/Localization/AppResources.resx
dest: /src/App/Resources/%original_file_name% dest: /src/Core/Resources/Localization/%original_file_name%
translation: /src/App/Resources/AppResources.%two_letters_code%.resx translation: /src/Core/Resources/Localization/AppResources.%two_letters_code%.resx
update_option: update_as_unapproved update_option: update_as_unapproved
languages_mapping: languages_mapping:
two_letters_code: two_letters_code:

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2024.2.1" android:installLocation="internalOnly" package="com.x8bit.bitwarden"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2024.3.0" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" /> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.NFC" />
@@ -43,6 +43,9 @@
<!-- Support for Xamarin.Essentials.Browser.OpenAsync (for Android > 11) --> <!-- Support for Xamarin.Essentials.Browser.OpenAsync (for Android > 11) -->
<!-- Related docs: https://learn.microsoft.com/en-us/xamarin/essentials/open-browser?tabs=android --> <!-- Related docs: https://learn.microsoft.com/en-us/xamarin/essentials/open-browser?tabs=android -->
<queries> <queries>
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
<intent> <intent>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<data android:scheme="http" /> <data android:scheme="http" />

View File

@@ -347,7 +347,7 @@ namespace Bit.Droid.Autofill
// InlinePresentation requires nonNull pending intent (even though we only utilize one for the // InlinePresentation requires nonNull pending intent (even though we only utilize one for the
// "my vault" presentation) so we're including an empty one here // "my vault" presentation) so we're including an empty one here
pendingIntent = PendingIntent.GetService(context, 0, new Intent(), pendingIntent = PendingIntent.GetService(context, 0, new Intent(),
AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.OneShot | PendingIntentFlags.UpdateCurrent, true)); AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.OneShot | PendingIntentFlags.UpdateCurrent, false));
} }
var slice = CreateInlinePresentationSlice( var slice = CreateInlinePresentationSlice(
inlinePresentationSpec, inlinePresentationSpec,

View File

@@ -79,24 +79,29 @@ namespace Bit.Droid.Services
} }
var context = Android.App.Application.Context; var context = Android.App.Application.Context;
var intent = new Intent(context, typeof(MainActivity)); var intent = context.PackageManager?.GetLaunchIntentForPackage(context.PackageName ?? string.Empty);
intent.PutExtra(Bit.Core.Constants.NotificationData, JsonConvert.SerializeObject(data));
var pendingIntentFlags = AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.UpdateCurrent, true);
var pendingIntent = PendingIntent.GetActivity(context, 20220801, intent, pendingIntentFlags);
var deleteIntent = new Intent(context, typeof(NotificationDismissReceiver)); var builder = new NotificationCompat.Builder(context, Bit.Core.Constants.AndroidNotificationChannelId);
deleteIntent.PutExtra(Bit.Core.Constants.NotificationData, JsonConvert.SerializeObject(data)); if(intent != null && context.PackageManager != null && !string.IsNullOrEmpty(context.PackageName))
var deletePendingIntent = PendingIntent.GetBroadcast(context, 20220802, deleteIntent, pendingIntentFlags); {
intent.PutExtra(Bit.Core.Constants.NotificationData, JsonConvert.SerializeObject(data));
var pendingIntentFlags = AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.UpdateCurrent, true);
var pendingIntent = PendingIntent.GetActivity(context, 20220801, intent, pendingIntentFlags);
var builder = new NotificationCompat.Builder(context, Bit.Core.Constants.AndroidNotificationChannelId) var deleteIntent = new Intent(context, typeof(NotificationDismissReceiver));
.SetContentIntent(pendingIntent) deleteIntent.PutExtra(Bit.Core.Constants.NotificationData, JsonConvert.SerializeObject(data));
.SetContentTitle(title) var deletePendingIntent = PendingIntent.GetBroadcast(context, 20220802, deleteIntent, pendingIntentFlags);
builder.SetContentIntent(pendingIntent)
.SetDeleteIntent(deletePendingIntent);
}
builder.SetContentTitle(title)
.SetContentText(message) .SetContentText(message)
.SetSmallIcon(Bit.Core.Resource.Drawable.ic_notification) .SetSmallIcon(Bit.Core.Resource.Drawable.ic_notification)
.SetColor((int)Android.Graphics.Color.White) .SetColor((int)Android.Graphics.Color.White)
.SetDeleteIntent(deletePendingIntent)
.SetAutoCancel(true); .SetAutoCancel(true);
if (data is PasswordlessNotificationData passwordlessNotificationData && passwordlessNotificationData.TimeoutInMinutes > 0) if (data is PasswordlessNotificationData passwordlessNotificationData && passwordlessNotificationData.TimeoutInMinutes > 0)
{ {
builder.SetTimeoutAfter(passwordlessNotificationData.TimeoutInMinutes * 60000); builder.SetTimeoutAfter(passwordlessNotificationData.TimeoutInMinutes * 60000);

View File

@@ -8,6 +8,7 @@ using Bit.Core.Abstractions;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Bit.Droid.Accessibility; using Bit.Droid.Accessibility;
using Java.Lang; using Java.Lang;
using Bit.App.Droid.Utilities;
namespace Bit.Droid.Tile namespace Bit.Droid.Tile
{ {
@@ -76,7 +77,7 @@ namespace Bit.Droid.Tile
var intent = new Intent(this, typeof(AccessibilityActivity)); var intent = new Intent(this, typeof(AccessibilityActivity));
intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop); intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop);
intent.PutExtra("autofillTileClicked", true); intent.PutExtra("autofillTileClicked", true);
StartActivityAndCollapse(intent); this.StartActivityAndCollapseWithIntent(intent, isMutable: true);
} }
private void ShowConfigErrorDialog() private void ShowConfigErrorDialog()

View File

@@ -1,15 +1,8 @@
using System; using Android.App;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content; using Android.Content;
using Android.OS;
using Android.Runtime; using Android.Runtime;
using Android.Service.QuickSettings; using Android.Service.QuickSettings;
using Android.Views; using Bit.App.Droid.Utilities;
using Android.Widget;
using Java.Lang; using Java.Lang;
namespace Bit.Droid.Tile namespace Bit.Droid.Tile
@@ -62,7 +55,7 @@ namespace Bit.Droid.Tile
var intent = new Intent(this, typeof(MainActivity)); var intent = new Intent(this, typeof(MainActivity));
intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop); intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop);
intent.PutExtra("generatorTile", true); intent.PutExtra("generatorTile", true);
StartActivityAndCollapse(intent); this.StartActivityAndCollapseWithIntent(intent, isMutable: false);
} }
} }
} }

View File

@@ -1,15 +1,8 @@
using System; using Android.App;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content; using Android.Content;
using Android.OS;
using Android.Runtime; using Android.Runtime;
using Android.Service.QuickSettings; using Android.Service.QuickSettings;
using Android.Views; using Bit.App.Droid.Utilities;
using Android.Widget;
using Java.Lang; using Java.Lang;
namespace Bit.Droid.Tile namespace Bit.Droid.Tile
@@ -63,7 +56,7 @@ namespace Bit.Droid.Tile
var intent = new Intent(this, typeof(MainActivity)); var intent = new Intent(this, typeof(MainActivity));
intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop); intent.SetFlags(ActivityFlags.NewTask | ActivityFlags.SingleTop | ActivityFlags.ClearTop);
intent.PutExtra("myVaultTile", true); intent.PutExtra("myVaultTile", true);
StartActivityAndCollapse(intent); this.StartActivityAndCollapseWithIntent(intent, isMutable: false);
} }
} }
} }

View File

@@ -2,6 +2,7 @@
using Android.Content; using Android.Content;
using Android.OS; using Android.OS;
using Android.Provider; using Android.Provider;
using Android.Service.QuickSettings;
using Bit.App.Utilities; using Bit.App.Utilities;
namespace Bit.App.Droid.Utilities namespace Bit.App.Droid.Utilities
@@ -64,5 +65,26 @@ namespace Bit.App.Droid.Utilities
return pendingIntentFlags; return pendingIntentFlags;
} }
public static void StartActivityAndCollapseWithIntent(this TileService service, Intent intent, bool isMutable)
{
//For Android 14+ We need to use PendingIntent instead of Intent directly. Older versions still need to use Intent.
if (Build.VERSION.SdkInt < BuildVersionCodes.UpsideDownCake)
{
service.StartActivityAndCollapse(intent);
return;
}
var pendingIntent = PendingIntent.GetActivity(
service.ApplicationContext,
0,
intent,
AddPendingIntentMutabilityFlag(PendingIntentFlags.UpdateCurrent, isMutable)
);
if (pendingIntent == null)
{
return;
}
service.StartActivityAndCollapse(pendingIntent);
}
} }
} }

View File

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

View File

@@ -5,7 +5,8 @@ namespace Bit.Core.Abstractions
{ {
public enum AwaiterPrecondition public enum AwaiterPrecondition
{ {
EnvironmentUrlsInited EnvironmentUrlsInited,
AndroidWindowCreated
} }
public interface IConditionedAwaiterManager public interface IConditionedAwaiterManager

View File

@@ -46,7 +46,6 @@ namespace Bit.App
// This queue keeps those actions so that when the app has resumed they can still be executed. // This queue keeps those actions so that when the app has resumed they can still be executed.
// Links: https://github.com/dotnet/maui/issues/11501 and https://bitwarden.atlassian.net/wiki/spaces/NMME/pages/664862722/MainPage+Assignments+not+working+on+Android+on+Background+or+App+resume // Links: https://github.com/dotnet/maui/issues/11501 and https://bitwarden.atlassian.net/wiki/spaces/NMME/pages/664862722/MainPage+Assignments+not+working+on+Android+on+Background+or+App+resume
private readonly Queue<Action> _onResumeActions = new Queue<Action>(); private readonly Queue<Action> _onResumeActions = new Queue<Action>();
private bool _hasNavigatedToAutofillWindow;
#if ANDROID #if ANDROID
@@ -120,41 +119,8 @@ namespace Bit.App
return new Window(new NavigationPage()); //No actual page needed. Only used for auto-filling the fields directly (externally) return new Window(new NavigationPage()); //No actual page needed. Only used for auto-filling the fields directly (externally)
} }
//"Internal" Autofill and Uri/Otp/CreateSend. This is where we create the autofill specific Window _isResumed = true;
if (Options != null && (Options.FromAutofillFramework || Options.Uri != null || Options.OtpData != null || Options.CreateSend != null)) return new ResumeWindow(new NavigationPage(new AndroidNavigationRedirectPage(Options)));
{
_isResumed = true; //Specifically for the Autofill scenario we need to manually set the _isResumed here
_hasNavigatedToAutofillWindow = true;
return new AutoFillWindow(new NavigationPage(new AndroidNavigationRedirectPage()));
}
var homePage = new HomePage(Options);
// WORKAROUND: If the user autofills with Accessibility Services enabled and goes back to the application then there is currently an issue
// where this method is called again
// thus it goes through here and the user goes to HomePage as we see here.
// So to solve this, the next flag check has been added which then turns on a flag on the home page
// that will trigger a navigation on the accounts manager when it loads; workarounding this behavior and navigating the user
// to the proper page depending on its state.
// WARNING: this doens't navigate the user to where they were but it acts as if the user had changed their account.
if(_hasNavigatedToAutofillWindow)
{
homePage.PerformNavigationOnAccountChangedOnLoad = true;
// this is needed because when coming back from AutofillWindow OnResume won't be called and we need this flag
// so that void Navigate(NavigationTarget navTarget, INavigationParams navParams) doesn't enqueue the navigation
// and it performs it directly.
_isResumed = true;
_hasNavigatedToAutofillWindow = false;
}
//If we have an existing MainAppWindow we can use that one
var mainAppWindow = Windows.OfType<MainAppWindow>().FirstOrDefault();
if (mainAppWindow != null)
{
mainAppWindow.PendingPage = new NavigationPage(homePage);
}
//Create new main window
return new MainAppWindow(new NavigationPage(homePage));
} }
#else #else
//iOS doesn't use the CreateWindow override used in Android so we just set the Application.Current.MainPage directly //iOS doesn't use the CreateWindow override used in Android so we just set the Application.Current.MainPage directly
@@ -171,7 +137,7 @@ namespace Bit.App
Application.Current.MainPage = value; Application.Current.MainPage = value;
} }
} }
} }
#endif #endif
public App() : this(null) public App() : this(null)

View File

@@ -47,6 +47,7 @@ namespace Bit.Core
public const string ConfigsKey = "configsKey"; public const string ConfigsKey = "configsKey";
public const string DisplayEuEnvironmentFlag = "display-eu-environment"; public const string DisplayEuEnvironmentFlag = "display-eu-environment";
public const string RegionEnvironment = "regionEnvironment"; public const string RegionEnvironment = "regionEnvironment";
public const string DuoCallback = "bitwarden://duo-callback";
/// <summary> /// <summary>
/// This key is used to store the value of "ShouldConnectToWatch" of the last user that had logged in /// This key is used to store the value of "ShouldConnectToWatch" of the last user that had logged in

View File

@@ -53,12 +53,13 @@ namespace Bit.App.Controls
if (BindingContext is CipherItemViewModel cipherItemVM) if (BindingContext is CipherItemViewModel cipherItemVM)
{ {
cipherItemVM.IconImageSuccesfullyLoaded = true; cipherItemVM.IconImageSuccesfullyLoaded = true;
MainThread.BeginInvokeOnMainThread(() =>
{
Icon.IsVisible = cipherItemVM.ShowIconImage;
IconPlaceholder.IsVisible = !cipherItemVM.ShowIconImage;
});
} }
MainThread.BeginInvokeOnMainThread(() =>
{
Icon.IsVisible = true;
IconPlaceholder.IsVisible = false;
});
} }
public void Icon_Error(object sender, FFImageLoading.Maui.CachedImageEvents.ErrorEventArgs e) public void Icon_Error(object sender, FFImageLoading.Maui.CachedImageEvents.ErrorEventArgs e)

View File

@@ -77,6 +77,7 @@
<Folder Include="Resources\Localization\" /> <Folder Include="Resources\Localization\" />
<Folder Include="Controls\Picker\" /> <Folder Include="Controls\Picker\" />
<Folder Include="Controls\Avatar\" /> <Folder Include="Controls\Avatar\" />
<Folder Include="Utilities\WebAuthenticatorMAUI\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<MauiImage Include="Resources\Images\dotnet_bot.svg"> <MauiImage Include="Resources\Images\dotnet_bot.svg">
@@ -107,5 +108,6 @@
<ItemGroup> <ItemGroup>
<None Remove="Controls\Picker\" /> <None Remove="Controls\Picker\" />
<None Remove="Controls\Avatar\" /> <None Remove="Controls\Avatar\" />
<None Remove="Utilities\WebAuthenticatorMAUI\" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,6 +1,7 @@
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Resources.Localization; using Bit.Core.Resources.Localization;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Microsoft.Maui.Platform;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@@ -26,7 +27,7 @@ namespace Bit.App.Pages
_apiEntry.ReturnCommand = new Command(() => _identityEntry.Focus()); _apiEntry.ReturnCommand = new Command(() => _identityEntry.Focus());
_identityEntry.ReturnType = ReturnType.Next; _identityEntry.ReturnType = ReturnType.Next;
_identityEntry.ReturnCommand = new Command(() => _iconsEntry.Focus()); _identityEntry.ReturnCommand = new Command(() => _iconsEntry.Focus());
_vm.SubmitSuccessAction = () => MainThread.BeginInvokeOnMainThread(async () => await SubmitSuccessAsync()); _vm.SubmitSuccessTask = () => MainThread.InvokeOnMainThreadAsync(SubmitSuccessAsync);
_vm.CloseAction = async () => _vm.CloseAction = async () =>
{ {
await Navigation.PopModalAsync(); await Navigation.PopModalAsync();
@@ -37,6 +38,12 @@ namespace Bit.App.Pages
{ {
_platformUtilsService.ShowToast("success", null, AppResources.EnvironmentSaved); _platformUtilsService.ShowToast("success", null, AppResources.EnvironmentSaved);
await Navigation.PopModalAsync(); await Navigation.PopModalAsync();
#if ANDROID
if (Platform.CurrentActivity.CurrentFocus != null)
{
Platform.CurrentActivity.HideKeyboard(Platform.CurrentActivity.CurrentFocus);
}
#endif
} }
private void Close_Clicked(object sender, EventArgs e) private void Close_Clicked(object sender, EventArgs e)

View File

@@ -44,7 +44,7 @@ namespace Bit.App.Pages
public string WebVaultUrl { get; set; } public string WebVaultUrl { get; set; }
public string IconsUrl { get; set; } public string IconsUrl { get; set; }
public string NotificationsUrls { get; set; } public string NotificationsUrls { get; set; }
public Action SubmitSuccessAction { get; set; } public Func<Task> SubmitSuccessTask { get; set; }
public Action CloseAction { get; set; } public Action CloseAction { get; set; }
public async Task SubmitAsync() public async Task SubmitAsync()
@@ -73,7 +73,10 @@ namespace Bit.App.Pages
IconsUrl = resUrls.Icons; IconsUrl = resUrls.Icons;
NotificationsUrls = resUrls.Notifications; NotificationsUrls = resUrls.Notifications;
SubmitSuccessAction?.Invoke(); if (SubmitSuccessTask != null)
{
await SubmitSuccessTask();
}
} }
public bool ValidateUrls() public bool ValidateUrls()

View File

@@ -12,12 +12,14 @@ namespace Bit.App.Pages
private readonly HomeViewModel _vm; private readonly HomeViewModel _vm;
private readonly AppOptions _appOptions; private readonly AppOptions _appOptions;
private IBroadcasterService _broadcasterService; private IBroadcasterService _broadcasterService;
private IConditionedAwaiterManager _conditionedAwaiterManager;
readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>(); readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>();
public HomePage(AppOptions appOptions = null) public HomePage(AppOptions appOptions = null)
{ {
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>(); _broadcasterService = ServiceContainer.Resolve<IBroadcasterService>();
_conditionedAwaiterManager = ServiceContainer.Resolve<IConditionedAwaiterManager>();
_appOptions = appOptions; _appOptions = appOptions;
InitializeComponent(); InitializeComponent();
_vm = BindingContext as HomeViewModel; _vm = BindingContext as HomeViewModel;
@@ -56,6 +58,8 @@ namespace Bit.App.Pages
PerformNavigationOnAccountChangedOnLoad = false; PerformNavigationOnAccountChangedOnLoad = false;
accountsManager.NavigateOnAccountChangeAsync().FireAndForget(); accountsManager.NavigateOnAccountChangeAsync().FireAndForget();
} }
_conditionedAwaiterManager.SetAsCompleted(AwaiterPrecondition.AndroidWindowCreated);
#endif #endif
} }

View File

@@ -39,7 +39,7 @@
FontSize="Small" FontSize="Small"
FontAttributes="Bold"/> FontAttributes="Bold"/>
<controls:MonoLabel <controls:MonoLabel
FormattedText="{Binding LoginRequest.FingerprintPhrase}" Text="{Binding LoginRequest.FingerprintPhrase}"
FontSize="Medium" FontSize="Medium"
TextColor="{DynamicResource FingerprintPhrase}" TextColor="{DynamicResource FingerprintPhrase}"
Margin="0,0,0,27" Margin="0,0,0,27"
@@ -85,7 +85,6 @@
<Button <Button
Text="{u:I18n DenyLogIn}" Text="{u:I18n DenyLogIn}"
Command="{Binding RejectRequestCommand}" Command="{Binding RejectRequestCommand}"
StyleClass="btn-secundary"
AutomationId="DenyLoginButton" /> AutomationId="DenyLoginButton" />
</StackLayout> </StackLayout>

View File

@@ -41,7 +41,7 @@
FontSize="Small" FontSize="Small"
FontAttributes="Bold" /> FontAttributes="Bold" />
<controls:MonoLabel <controls:MonoLabel
FormattedText="{Binding FingerprintPhrase}" Text="{Binding FingerprintPhrase}"
FontSize="Small" FontSize="Small"
TextColor="{DynamicResource FingerprintPhrase}" TextColor="{DynamicResource FingerprintPhrase}"
AutomationId="FingerprintPhraseValue" /> AutomationId="FingerprintPhraseValue" />

View File

@@ -21,6 +21,7 @@ namespace Bit.App.Pages
InitializeComponent(); InitializeComponent();
_vm = BindingContext as LoginSsoPageViewModel; _vm = BindingContext as LoginSsoPageViewModel;
_vm.Page = this; _vm.Page = this;
_vm.FromIosExtension = _appOptions?.IosExtension ?? false;
_vm.StartTwoFactorAction = () => MainThread.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync()); _vm.StartTwoFactorAction = () => MainThread.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync());
_vm.StartSetPasswordAction = () => _vm.StartSetPasswordAction = () =>
MainThread.BeginInvokeOnMainThread(async () => await StartSetPasswordAsync()); MainThread.BeginInvokeOnMainThread(async () => await StartSetPasswordAsync());

View File

@@ -15,6 +15,16 @@ using Bit.Core.Utilities;
using Microsoft.Maui.Authentication; using Microsoft.Maui.Authentication;
using Microsoft.Maui.Networking; using Microsoft.Maui.Networking;
using NetworkAccess = Microsoft.Maui.Networking.NetworkAccess; using NetworkAccess = Microsoft.Maui.Networking.NetworkAccess;
using Org.BouncyCastle.Asn1.Ocsp;
#if IOS
using AuthenticationServices;
using Foundation;
using UIKit;
using WebAuthenticator = Bit.Core.Utilities.MAUI.WebAuthenticator;
using WebAuthenticatorResult = Bit.Core.Utilities.MAUI.WebAuthenticatorResult;
using WebAuthenticatorOptions = Bit.Core.Utilities.MAUI.WebAuthenticatorOptions;
#endif
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@@ -64,6 +74,8 @@ namespace Bit.App.Pages
set => SetProperty(ref _orgIdentifier, value); set => SetProperty(ref _orgIdentifier, value);
} }
public bool FromIosExtension { get; set; }
public ICommand LogInCommand { get; } public ICommand LogInCommand { get; }
public Action StartTwoFactorAction { get; set; } public Action StartTwoFactorAction { get; set; }
public Action StartSetPasswordAction { get; set; } public Action StartSetPasswordAction { get; set; }
@@ -153,6 +165,9 @@ namespace Bit.App.Pages
CallbackUrl = new Uri(REDIRECT_URI), CallbackUrl = new Uri(REDIRECT_URI),
Url = new Uri(url), Url = new Uri(url),
PrefersEphemeralWebBrowserSession = _useEphemeralWebBrowserSession, PrefersEphemeralWebBrowserSession = _useEphemeralWebBrowserSession,
#if IOS
ShouldUseSharedApplicationKeyWindow = FromIosExtension
#endif
}); });
var code = GetResultCode(authResult, state); var code = GetResultCode(authResult, state);

View File

@@ -132,14 +132,26 @@
</StackLayout> </StackLayout>
</StackLayout> </StackLayout>
</StackLayout> </StackLayout>
<StackLayout Spacing="0" Padding="0" IsVisible="{Binding DuoMethod, Mode=OneWay}" <StackLayout
VerticalOptions="StartAndExpand"> Spacing="0"
Padding="0"
IsVisible="{Binding DuoMethod, Mode=OneWay}"
VerticalOptions="FillAndExpand">
<Label
StyleClass="box"
Text="{Binding DuoFramelessLabel}"
HorizontalOptions="StartAndExpand"
Margin="10,21"
IsVisible="{Binding IsDuoFrameless}"/>
<controls:HybridWebView <controls:HybridWebView
x:Name="_duoWebView" x:Name="_duoWebView"
HorizontalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
HeightRequest="{Binding DuoWebViewHeight, Mode=OneWay}" /> HeightRequest="{Binding DuoWebViewHeight, Mode=OneWay}"
<StackLayout StyleClass="box" VerticalOptions="End"> IsVisible="{Binding IsDuoFrameless, Converter={StaticResource inverseBool}}"/>
<StackLayout
StyleClass="box"
VerticalOptions="End">
<StackLayout StyleClass="box-row, box-row-switch"> <StackLayout StyleClass="box-row, box-row-switch">
<Label <Label
Text="{u:I18n RememberMe}" Text="{u:I18n RememberMe}"
@@ -151,6 +163,12 @@
HorizontalOptions="End" /> HorizontalOptions="End" />
</StackLayout> </StackLayout>
</StackLayout> </StackLayout>
<Button Text="{u:I18n LaunchDuo}"
Margin="10,21"
StyleClass="btn-primary"
Command="{Binding AuthenticateWithDuoFramelessCommand}"
AutomationId="DuoFramelessButton"
IsVisible="{Binding IsDuoFrameless}"/>
</StackLayout> </StackLayout>
<StackLayout <StackLayout
Spacing="0" Spacing="0"

View File

@@ -2,6 +2,7 @@
using System.Windows.Input; using System.Windows.Input;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Exceptions; using Bit.Core.Exceptions;
@@ -34,6 +35,7 @@ namespace Bit.App.Pages
private string _webVaultUrl = "https://vault.bitwarden.com"; private string _webVaultUrl = "https://vault.bitwarden.com";
private bool _enableContinue = false; private bool _enableContinue = false;
private bool _showContinue = true; private bool _showContinue = true;
private bool _isDuoFrameless = false;
private double _duoWebViewHeight; private double _duoWebViewHeight;
public TwoFactorPageViewModel() public TwoFactorPageViewModel()
@@ -56,6 +58,7 @@ namespace Bit.App.Pages
PageTitle = AppResources.TwoStepLogin; PageTitle = AppResources.TwoStepLogin;
SubmitCommand = CreateDefaultAsyncRelayCommand(() => MainThread.InvokeOnMainThreadAsync(async () => await SubmitAsync()), allowsMultipleExecutions: false); SubmitCommand = CreateDefaultAsyncRelayCommand(() => MainThread.InvokeOnMainThreadAsync(async () => await SubmitAsync()), allowsMultipleExecutions: false);
MoreCommand = CreateDefaultAsyncRelayCommand(MoreAsync, onException: _logger.Exception, allowsMultipleExecutions: false); MoreCommand = CreateDefaultAsyncRelayCommand(MoreAsync, onException: _logger.Exception, allowsMultipleExecutions: false);
AuthenticateWithDuoFramelessCommand = CreateDefaultAsyncRelayCommand(DuoFramelessAuthenticateAsync, allowsMultipleExecutions: false);
} }
public string TotpInstruction public string TotpInstruction
@@ -103,6 +106,16 @@ namespace Bit.App.Pages
set => SetProperty(ref _enableContinue, value); set => SetProperty(ref _enableContinue, value);
} }
public bool IsDuoFrameless
{
get => _isDuoFrameless;
set => SetProperty(ref _isDuoFrameless, value, additionalPropertyNames: new string[] { nameof(DuoFramelessLabel) });
}
public string DuoFramelessLabel => SelectedProviderType == TwoFactorProviderType.OrganizationDuo ?
$"{AppResources.DuoTwoStepLoginIsRequiredForYourAccount} {AppResources.FollowTheStepsFromDuoToFinishLoggingIn}" :
AppResources.FollowTheStepsFromDuoToFinishLoggingIn;
#if IOS #if IOS
public string YubikeyInstruction => AppResources.YubiKeyInstructionIos; public string YubikeyInstruction => AppResources.YubiKeyInstructionIos;
#else #else
@@ -125,6 +138,7 @@ namespace Bit.App.Pages
} }
public ICommand SubmitCommand { get; } public ICommand SubmitCommand { get; }
public ICommand MoreCommand { get; } public ICommand MoreCommand { get; }
public ICommand AuthenticateWithDuoFramelessCommand { get; }
public Action TwoFactorAuthSuccessAction { get; set; } public Action TwoFactorAuthSuccessAction { get; set; }
public Action LockAction { get; set; } public Action LockAction { get; set; }
public Action StartDeviceApprovalOptionsAction { get; set; } public Action StartDeviceApprovalOptionsAction { get; set; }
@@ -179,15 +193,29 @@ namespace Bit.App.Pages
break; break;
case TwoFactorProviderType.Duo: case TwoFactorProviderType.Duo:
case TwoFactorProviderType.OrganizationDuo: case TwoFactorProviderType.OrganizationDuo:
SetDuoWebViewHeight(); IsDuoFrameless = providerData.ContainsKey("AuthUrl");
var host = WebUtility.UrlEncode(providerData["Host"] as string); if (!IsDuoFrameless)
var req = WebUtility.UrlEncode(providerData["Signature"] as string);
page.DuoWebView.Uri = $"{_webVaultUrl}/duo-connector.html?host={host}&request={req}";
page.DuoWebView.RegisterAction(sig =>
{ {
Token = sig; SetDuoWebViewHeight();
SubmitCommand.Execute(null); var host = WebUtility.UrlEncode(providerData["Host"] as string);
}); var req = WebUtility.UrlEncode(providerData["Signature"] as string);
page.DuoWebView.Uri = $"{_webVaultUrl}/duo-connector.html?host={host}&request={req}";
page.DuoWebView.RegisterAction(sig =>
{
Token = sig;
MainThread.BeginInvokeOnMainThread(async () =>
{
try
{
await SubmitAsync();
}
catch (Exception ex)
{
HandleException(ex);
}
});
});
}
break; break;
case TwoFactorProviderType.Email: case TwoFactorProviderType.Email:
TotpInstruction = string.Format(AppResources.EnterVerificationCodeEmail, TotpInstruction = string.Format(AppResources.EnterVerificationCodeEmail,
@@ -211,6 +239,77 @@ namespace Bit.App.Pages
ShowContinue = !(SelectedProviderType == null || DuoMethod || Fido2Method); ShowContinue = !(SelectedProviderType == null || DuoMethod || Fido2Method);
} }
private async Task DuoFramelessAuthenticateAsync()
{
await _deviceActionService.ShowLoadingAsync(AppResources.Validating);
if (!_authService.TwoFactorProvidersData.TryGetValue(SelectedProviderType.Value, out var providerData) ||
!providerData.TryGetValue("AuthUrl", out var urlObject))
{
throw new InvalidOperationException("Duo authentication error: Could not get ProviderData or AuthUrl");
}
var url = urlObject as string;
if (string.IsNullOrWhiteSpace(url))
{
throw new ArgumentNullException("Duo authentication error: Could not get valid auth url");
}
WebAuthenticatorResult authResult;
try
{
authResult = await WebAuthenticator.AuthenticateAsync(new WebAuthenticatorOptions
{
Url = new Uri(url),
CallbackUrl = new Uri(Constants.DuoCallback)
});
}
catch (TaskCanceledException)
{
// user canceled
await _deviceActionService.HideLoadingAsync();
return;
}
await _deviceActionService.HideLoadingAsync();
if (authResult == null || authResult.Properties == null)
{
throw new InvalidOperationException("Duo authentication error: Could not get result from authentication");
}
if (authResult.Properties.TryGetValue("error", out var resultError))
{
_logger.Error(resultError);
await _platformUtilsService.ShowDialogAsync(AppResources.AnErrorHasOccurred, AppResources.Ok);
return;
}
string code = null;
if (authResult.Properties.TryGetValue("code", out var resultCodeData))
{
code = Uri.UnescapeDataString(resultCodeData);
}
if (string.IsNullOrWhiteSpace(code))
{
throw new ArgumentException("Duo authentication error: response code is null or empty/whitespace");
}
string state = null;
if (authResult.Properties.TryGetValue("state", out var resultStateData))
{
state = Uri.UnescapeDataString(resultStateData);
}
if (string.IsNullOrWhiteSpace(state))
{
throw new ArgumentException("Duo authentication error: response state is null or empty/whitespace");
}
Token = $"{code}|{state}";
await SubmitAsync(true);
}
public void SetDuoWebViewHeight() public void SetDuoWebViewHeight()
{ {
var screenHeight = DeviceDisplay.MainDisplayInfo.Height / DeviceDisplay.MainDisplayInfo.Density; var screenHeight = DeviceDisplay.MainDisplayInfo.Height / DeviceDisplay.MainDisplayInfo.Density;

View File

@@ -1,20 +1,40 @@
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Models;
using Bit.App.Pages;
using Bit.Core.Abstractions;
using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
namespace Bit.Core.Pages; namespace Bit.Core.Pages;
public partial class AndroidNavigationRedirectPage : ContentPage public partial class AndroidNavigationRedirectPage : ContentPage
{ {
private readonly IAccountsManager _accountsManager; private AppOptions _options;
public AndroidNavigationRedirectPage(AppOptions options)
public AndroidNavigationRedirectPage()
{ {
_accountsManager = ServiceContainer.Resolve<IAccountsManager>("accountsManager"); _options = options ?? new AppOptions();
InitializeComponent(); InitializeComponent();
} }
private void AndroidNavigationRedirectPage_OnLoaded(object sender, EventArgs e) private void AndroidNavigationRedirectPage_OnLoaded(object sender, EventArgs e)
{ {
_accountsManager.NavigateOnAccountChangeAsync().FireAndForget(); if (ServiceContainer.TryResolve<IAccountsManager>(out var accountsManager))
{
accountsManager.NavigateOnAccountChangeAsync().FireAndForget();
}
else
{
Bit.App.App.MainPage = new NavigationPage(new HomePage(_options)); //Fallback scenario to load HomePage just in case something goes wrong when resolving IAccountsManager
}
if (ServiceContainer.TryResolve<IConditionedAwaiterManager>(out var conditionedAwaiterManager))
{
conditionedAwaiterManager?.SetAsCompleted(AwaiterPrecondition.AndroidWindowCreated);
}
else
{
LoggerHelper.LogEvenIfCantBeResolved(new InvalidOperationException("ConditionedAwaiterManager can't be resolved on Android Navigation redirection"));
}
} }
} }

View File

@@ -266,6 +266,8 @@
AutomationId="SendShowHideOptionsButton" /> AutomationId="SendShowHideOptionsButton" />
<controls:IconButton <controls:IconButton
x:Name="_btnOptionsUp" x:Name="_btnOptionsUp"
InputTransparent="True"
MinimumWidthRequest="25"
Text="{Binding Source={x:Static core:BitwardenIcons.ChevronUp}}" Text="{Binding Source={x:Static core:BitwardenIcons.ChevronUp}}"
StyleClass="box-row-button" StyleClass="box-row-button"
TextColor="{DynamicResource PrimaryColor}" TextColor="{DynamicResource PrimaryColor}"
@@ -274,6 +276,8 @@
AutomationId="SendOptionsDisplayed" /> AutomationId="SendOptionsDisplayed" />
<controls:IconButton <controls:IconButton
x:Name="_btnOptionsDown" x:Name="_btnOptionsDown"
InputTransparent="True"
MinimumWidthRequest="25"
Text="{Binding Source={x:Static core:BitwardenIcons.AngleDown}}" Text="{Binding Source={x:Static core:BitwardenIcons.AngleDown}}"
StyleClass="box-row-button" StyleClass="box-row-button"
TextColor="{DynamicResource PrimaryColor}" TextColor="{DynamicResource PrimaryColor}"

View File

@@ -50,6 +50,7 @@
x:DataType="pages:SendGroupingsPageListItem"> x:DataType="pages:SendGroupingsPageListItem">
<controls:ExtendedStackLayout Orientation="Horizontal" <controls:ExtendedStackLayout Orientation="Horizontal"
StyleClass="list-row, list-row-platform" StyleClass="list-row, list-row-platform"
Spacing="6"
AutomationId="{Binding AutomationId}"> AutomationId="{Binding AutomationId}">
<controls:IconLabel Text="{Binding Icon, Mode=OneWay}" <controls:IconLabel Text="{Binding Icon, Mode=OneWay}"
HorizontalOptions="Start" HorizontalOptions="Start"

View File

@@ -37,10 +37,9 @@
<Label <Label
Text="{u:I18n FingerprintPhrase}" Text="{u:I18n FingerprintPhrase}"
FontSize="Small" FontSize="Small"
Padding="0, 10, 0 ,0"
FontAttributes="Bold"/> FontAttributes="Bold"/>
<controls:MonoLabel <controls:MonoLabel
FormattedText="{Binding FingerprintPhrase}" Text="{Binding FingerprintPhrase}"
Grid.Row="1" Grid.Row="1"
Grid.ColumnSpan="2" Grid.ColumnSpan="2"
FontSize="Small" FontSize="Small"
@@ -70,64 +69,70 @@
Grid.ColumnSpan="2"/> Grid.ColumnSpan="2"/>
</Grid> </Grid>
</DataTemplate> </DataTemplate>
<StackLayout
x:Key="mainLayout"
x:Name="_mainLayout"
Padding="0, 10">
<RefreshView
IsRefreshing="{Binding IsRefreshing}"
Command="{Binding RefreshCommand}"
VerticalOptions="FillAndExpand"
BackgroundColor="{DynamicResource BackgroundColor}">
<StackLayout>
<Image
x:Name="_emptyPlaceholder"
Source="empty_login_requests"
HorizontalOptions="Center"
WidthRequest="160"
HeightRequest="160"
Margin="0,70,0,0"
IsVisible="{Binding HasLoginRequests, Converter={StaticResource inverseBool}}"
SemanticProperties.Description="{u:I18n NoPendingRequests}" />
<controls:CustomLabel
StyleClass="box-label-regular"
Text="{u:I18n NoPendingRequests}"
IsVisible="{Binding HasLoginRequests, Converter={StaticResource inverseBool}}"
FontAttributes="{OnPlatform iOS=Bold}"
FontWeight="500"
HorizontalTextAlignment="Center"
Margin="14,10,14,0"/>
<controls:ExtendedCollectionView
ItemsSource="{Binding LoginRequests}"
ItemTemplate="{StaticResource loginRequestTemplate}"
SelectionMode="Single"
IsVisible="{Binding HasLoginRequests}"
ExtraDataForLogging="Login requests page" >
<controls:ExtendedCollectionView.Behaviors>
<xct:EventToCommandBehavior
EventName="SelectionChanged"
Command="{Binding AnswerRequestCommand}"
EventArgsConverter="{StaticResource SelectionChangedEventArgsConverter}" />
</controls:ExtendedCollectionView.Behaviors>
</controls:ExtendedCollectionView>
</StackLayout>
</RefreshView>
<controls:IconLabelButton
VerticalOptions="End"
Margin="10,0"
Icon="{Binding Source={x:Static core:BitwardenIcons.Trash}}"
Label="{u:I18n DeclineAllRequests}"
ButtonCommand="{Binding DeclineAllRequestsCommand}"
IsVisible="{Binding HasLoginRequests}"
AutomationId="DeleteAllRequestsButton" />
</StackLayout>
</ResourceDictionary> </ResourceDictionary>
</ContentPage.Resources> </ContentPage.Resources>
<ContentView <Grid
x:Name="_mainContent"> RowDefinitions="*, Auto"
</ContentView> Padding="0, 10">
<RefreshView
Grid.Row="0"
IsRefreshing="{Binding IsRefreshing}"
Command="{Binding RefreshCommand}"
VerticalOptions="Fill"
BackgroundColor="{DynamicResource BackgroundColor}">
<Grid RowDefinitions="Auto, *">
<VerticalStackLayout Grid.Row="0"
HorizontalOptions="Center">
<Image
x:Name="_emptyPlaceholder"
Source="empty_login_requests"
WidthRequest="160"
HeightRequest="160"
Margin="0,70,0,0"
IsVisible="{Binding HasLoginRequests, Converter={StaticResource inverseBool}}"
SemanticProperties.Description="{u:I18n NoPendingRequests}" />
<controls:CustomLabel
StyleClass="box-label-regular"
Text="{u:I18n NoPendingRequests}"
IsVisible="{Binding HasLoginRequests, Converter={StaticResource inverseBool}}"
FontAttributes="{OnPlatform iOS=Bold}"
FontWeight="500"
Margin="14,10,14,0"/>
</VerticalStackLayout>
<controls:ExtendedCollectionView
Grid.Row="1"
ItemsSource="{Binding LoginRequests}"
ItemTemplate="{StaticResource loginRequestTemplate}"
SelectionMode="Single"
IsVisible="{Binding HasLoginRequests}"
ExtraDataForLogging="Login requests page" >
<controls:ExtendedCollectionView.Behaviors>
<xct:EventToCommandBehavior
EventName="SelectionChanged"
Command="{Binding AnswerRequestCommand}"
EventArgsConverter="{StaticResource SelectionChangedEventArgsConverter}" />
</controls:ExtendedCollectionView.Behaviors>
</controls:ExtendedCollectionView>
</Grid>
</RefreshView>
<controls:IconLabelButton
Grid.Row="1"
VerticalOptions="End"
Margin="10,0"
Icon="{Binding Source={x:Static core:BitwardenIcons.Trash}}"
Label="{u:I18n DeclineAllRequests}"
ButtonCommand="{Binding DeclineAllRequestsCommand}"
IsVisible="{Binding HasLoginRequests}"
AutomationId="DeleteAllRequestsButton" />
<Grid x:Name="_activityIndicatorGrid" Grid.Row="0" Grid.RowSpan="2" BackgroundColor="{DynamicResource BackgroundColor}">
<ActivityIndicator IsRunning="True"
VerticalOptions="Center"
HorizontalOptions="Center" />
</Grid>
</Grid>
</pages:BaseContentPage> </pages:BaseContentPage>

View File

@@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Models.Response; using Bit.Core.Models.Response;
using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Microsoft.Maui.ApplicationModel; using Microsoft.Maui.ApplicationModel;
using Microsoft.Maui.Controls; using Microsoft.Maui.Controls;
@@ -19,7 +20,6 @@ namespace Bit.App.Pages
public LoginPasswordlessRequestsListPage() public LoginPasswordlessRequestsListPage()
{ {
InitializeComponent(); InitializeComponent();
SetActivityIndicator(_mainContent);
_vm = BindingContext as LoginPasswordlessRequestsListViewModel; _vm = BindingContext as LoginPasswordlessRequestsListViewModel;
_vm.Page = this; _vm.Page = this;
} }
@@ -27,9 +27,21 @@ namespace Bit.App.Pages
protected override async void OnAppearing() protected override async void OnAppearing()
{ {
base.OnAppearing(); base.OnAppearing();
await LoadOnAppearedAsync(_mainLayout, false, _vm.RefreshAsync, _mainContent); try
{
_activityIndicatorGrid.IsVisible = true;
UpdatePlaceholder(); await _vm.RefreshAsync();
UpdatePlaceholder();
}
catch (Exception ex)
{
LoggerHelper.LogEvenIfCantBeResolved(ex);
}
finally
{
_activityIndicatorGrid.IsVisible = false;
}
} }
private async void Close_Clicked(object sender, System.EventArgs e) private async void Close_Clicked(object sender, System.EventArgs e)

View File

@@ -66,7 +66,6 @@ namespace Bit.App.Pages
{ {
try try
{ {
IsRefreshing = true;
LoginRequests.ReplaceRange(await _authService.GetActivePasswordlessLoginRequestsAsync()); LoginRequests.ReplaceRange(await _authService.GetActivePasswordlessLoginRequestsAsync());
} }
catch (Exception ex) catch (Exception ex)
@@ -108,7 +107,7 @@ namespace Bit.App.Pages
Origin = loginRequestData.Origin Origin = loginRequestData.Origin
}); });
await Device.InvokeOnMainThreadAsync(() => Application.Current.MainPage.Navigation.PushModalAsync(new NavigationPage(page))); await MainThread.InvokeOnMainThreadAsync(() => Application.Current.MainPage.Navigation.PushModalAsync(new NavigationPage(page)));
} }
private async Task DeclineAllRequestsAsync() private async Task DeclineAllRequestsAsync()

View File

@@ -96,6 +96,14 @@ namespace Bit.App.Pages
if (message.Command == "syncCompleted") if (message.Command == "syncCompleted")
{ {
MainThread.BeginInvokeOnMainThread(async () => await UpdateVaultButtonTitleAsync()); MainThread.BeginInvokeOnMainThread(async () => await UpdateVaultButtonTitleAsync());
try
{
await ForcePasswordResetIfNeededAsync();
}
catch (Exception ex)
{
_logger.Value.Exception(ex);
}
} }
}); });
await UpdateVaultButtonTitleAsync(); await UpdateVaultButtonTitleAsync();

View File

@@ -2335,6 +2335,15 @@ namespace Bit.Core.Resources.Localization {
} }
} }
/// <summary>
/// Looks up a localized string similar to Duo two-step login is required for your account. .
/// </summary>
public static string DuoTwoStepLoginIsRequiredForYourAccount {
get {
return ResourceManager.GetString("DuoTwoStepLoginIsRequiredForYourAccount", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Edit. /// Looks up a localized string similar to Edit.
/// </summary> /// </summary>
@@ -3199,6 +3208,15 @@ namespace Bit.Core.Resources.Localization {
} }
} }
/// <summary>
/// Looks up a localized string similar to Follow the steps from Duo to finish logging in..
/// </summary>
public static string FollowTheStepsFromDuoToFinishLoggingIn {
get {
return ResourceManager.GetString("FollowTheStepsFromDuoToFinishLoggingIn", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to {0} is not correctly formatted.. /// Looks up a localized string similar to {0} is not correctly formatted..
/// </summary> /// </summary>
@@ -3793,6 +3811,15 @@ namespace Bit.Core.Resources.Localization {
} }
} }
/// <summary>
/// Looks up a localized string similar to Launch Duo.
/// </summary>
public static string LaunchDuo {
get {
return ResourceManager.GetString("LaunchDuo", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Bitwarden allows you to share your vault items with others by using an organization. Learn more on the bitwarden.com website.. /// Looks up a localized string similar to Bitwarden allows you to share your vault items with others by using an organization. Learn more on the bitwarden.com website..
/// </summary> /// </summary>

View File

@@ -2876,4 +2876,13 @@ Wil u na die rekening omskakel?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -276,7 +276,7 @@
<value>هل أنت متأكد من أنك تريد تسجيل الخروج؟</value> <value>هل أنت متأكد من أنك تريد تسجيل الخروج؟</value>
</data> </data>
<data name="RemoveAccount" xml:space="preserve"> <data name="RemoveAccount" xml:space="preserve">
<value>إزالة الحساب</value> <value>أزِل الحساب</value>
</data> </data>
<data name="RemoveAccountConfirmation" xml:space="preserve"> <data name="RemoveAccountConfirmation" xml:space="preserve">
<value>هل أنت متأكد من أنك تريد إزالة هذا الحساب؟</value> <value>هل أنت متأكد من أنك تريد إزالة هذا الحساب؟</value>
@@ -2822,7 +2822,7 @@
<value>مواصلة الاتصال بالدعم؟</value> <value>مواصلة الاتصال بالدعم؟</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve"> <data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value> <value>هل تريد المتابعة إلى سياسة الخصوصية؟</value>
</data> </data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>هل تريد المتابعة إلى متجر التطبيقات؟</value> <value>هل تريد المتابعة إلى متجر التطبيقات؟</value>
@@ -2844,7 +2844,7 @@
<value>لا يمكن العثور على ما تبحث عنه؟ قم بالتواصل مع دعم Bitwarden على bitwarden.com.</value> <value>لا يمكن العثور على ما تبحث عنه؟ قم بالتواصل مع دعم Bitwarden على bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve"> <data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value> <value>اطلع على سياستنا للخصوصية على bitwarden.com.</value>
</data> </data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>استكشف المزيد من الميزات لحساب Bitwarden الخاص بك على تطبيق الويب.</value> <value>استكشف المزيد من الميزات لحساب Bitwarden الخاص بك على تطبيق الويب.</value>
@@ -2877,4 +2877,13 @@
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>أعدنّ ميزة إلغاء القُفْل لتغيير إجراء مهلة المخزن الخاص بك.</value> <value>أعدنّ ميزة إلغاء القُفْل لتغيير إجراء مهلة المخزن الخاص بك.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2875,4 +2875,13 @@ Bu hesaba keçmək istəyirsiniz?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Anbar vaxt bitməsi əməliyyatınızı dəyişdirmək üçün bir kilid açma seçimi qurun.</value> <value>Anbar vaxt bitməsi əməliyyatınızı dəyişdirmək üçün bir kilid açma seçimi qurun.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Hesabınız üçün Duo iki addımlı giriş tələb olunur. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Giriş etməni tamamlamaq üçün Duo-dakı addımları izləyin.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Duo-nu başlat</value>
</data>
</root> </root>

View File

@@ -2876,4 +2876,13 @@
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2876,4 +2876,13 @@
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Задайте начин за отключване, за да може да промените действието при изтичане на времето за достъп до трезора.</value> <value>Задайте начин за отключване, за да може да промените действието при изтичане на времето за достъп до трезора.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Вашата регистрация изисква двустепенно удостоверяване чрез Duo. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Следвайте стъпките от Duo, за да завършите вписването.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Стартиране на Duo</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2875,4 +2875,13 @@ Skeniranje će biti izvršeno automatski.</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2876,4 +2876,13 @@ Voleu canviar a aquest compte?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Configura una opció de desbloqueig per canviar l'acció de temps d'espera de la caixa forta.</value> <value>Configura una opció de desbloqueig per canviar l'acció de temps d'espera de la caixa forta.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Es requereix l'inici de sessió en dos passos de DUO al vostre compte. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Seguiu els passos de Duo per acabar d'iniciar la sessió.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Inicia DUO</value>
</data>
</root> </root>

View File

@@ -2875,4 +2875,13 @@ Chcete se přepnout na tento účet?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Nastavte volbu odemknutí, abyste změnili časový limit Vašeho trezoru.</value> <value>Nastavte volbu odemknutí, abyste změnili časový limit Vašeho trezoru.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Pro Váš účet je vyžadováno dvoufázové přihlášení DUO. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Postupujte podle kroků od DUO pro dokončení přihlášení.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Spustit DUO</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -907,7 +907,7 @@ Skanning vil ske automatisk.</value>
<value>Kopiér TOTP</value> <value>Kopiér TOTP</value>
</data> </data>
<data name="CopyTotpAutomaticallyDescription" xml:space="preserve"> <data name="CopyTotpAutomaticallyDescription" xml:space="preserve">
<value>Har et login en godkendelsesnøgle, kopiér TOTP-bekræftelseskoden til udklipsholderen, når login auto-udfyldes.</value> <value>Har et login en godkendelsesnøgle, kopiér da TOTP-bekræftelseskoden til udklipsholderen, når login autoudfyldes.</value>
</data> </data>
<data name="CopyTotpAutomatically" xml:space="preserve"> <data name="CopyTotpAutomatically" xml:space="preserve">
<value>Kopiér TOTP automatisk</value> <value>Kopiér TOTP automatisk</value>
@@ -2128,7 +2128,7 @@ Skanning vil ske automatisk.</value>
<value>Denne organisation har en virksomhedspolitik, der automatisk tilmelder dig til nulstilling af adgangskode. Tilmelding giver organisationsadministratorer mulighed for at skifte din hovedadgangskode.</value> <value>Denne organisation har en virksomhedspolitik, der automatisk tilmelder dig til nulstilling af adgangskode. Tilmelding giver organisationsadministratorer mulighed for at skifte din hovedadgangskode.</value>
</data> </data>
<data name="VaultTimeoutPolicyInEffect" xml:space="preserve"> <data name="VaultTimeoutPolicyInEffect" xml:space="preserve">
<value>Dine organisationspolitikker påvirker din boks-timeout. Maksimum tilladte boks-timeout er {0} time(r) og {1} minut(ter)</value> <value>Organisationspolitikkerne har sat den maksimalt tilladte bokstimeout til {0} tim(er) og {1} minut(ter).</value>
</data> </data>
<data name="VaultTimeoutPolicyWithActionInEffect" xml:space="preserve"> <data name="VaultTimeoutPolicyWithActionInEffect" xml:space="preserve">
<value>Organisationspolitikkerne påvirker boks-timeout. Maks. tilladt boks-timeout er {0} time(r) og {1} minut(ter). Boks-timeout er pt. sat til {2}.</value> <value>Organisationspolitikkerne påvirker boks-timeout. Maks. tilladt boks-timeout er {0} time(r) og {1} minut(ter). Boks-timeout er pt. sat til {2}.</value>
@@ -2354,7 +2354,7 @@ vælg Tilføj TOTP for at gemme nøglen sikkert</value>
<value>Godkend loginanmodninger</value> <value>Godkend loginanmodninger</value>
</data> </data>
<data name="UseThisDeviceToApproveLoginRequestsMadeFromOtherDevices" xml:space="preserve"> <data name="UseThisDeviceToApproveLoginRequestsMadeFromOtherDevices" xml:space="preserve">
<value>Brug denne enhed til at godkende loginanmodninger fra andre enheder.</value> <value>Brug denne enhed til at godkende loginanmodninger fra andre enheder</value>
</data> </data>
<data name="AllowNotifications" xml:space="preserve"> <data name="AllowNotifications" xml:space="preserve">
<value>Tillad notifikationer</value> <value>Tillad notifikationer</value>
@@ -2668,7 +2668,7 @@ Vil du skifte til denne konto?</value>
<value>Hjælp til genanmodning om hovedadgangskode</value> <value>Hjælp til genanmodning om hovedadgangskode</value>
</data> </data>
<data name="UnlockingMayFailDueToInsufficientMemoryDecreaseYourKDFMemorySettingsToResolve" xml:space="preserve"> <data name="UnlockingMayFailDueToInsufficientMemoryDecreaseYourKDFMemorySettingsToResolve" xml:space="preserve">
<value>Unlocking may fail due to insufficient memory. Decrease your KDF memory settings or set up biometric unlock to resolve.</value> <value>Oplåsning kan fejle grundet utilstrækkelig hukommelse. Reducér KDF-hukommelsesindstillinger eller opsæt biometrisk oplåsning for at afhjælpe.</value>
</data> </data>
<data name="InvalidAPIKey" xml:space="preserve"> <data name="InvalidAPIKey" xml:space="preserve">
<value>Ugyldig API-nøgle</value> <value>Ugyldig API-nøgle</value>
@@ -2876,4 +2876,13 @@ Vil du skifte til denne konto?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Opsæt en oplåsningsmetode for at ændre Bokstimeouthandlingen.</value> <value>Opsæt en oplåsningsmetode for at ændre Bokstimeouthandlingen.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo-totrinsindlogning kræves for kontoen. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Følg trinnene fra Duo for at færdiggøre indlogningen.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Start Duo</value>
</data>
</root> </root>

View File

@@ -2875,4 +2875,13 @@ Möchtest du zu diesem Konto wechseln?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Richte eine Entsperroption ein, um deine Aktion bei Tresor-Timeout zu ändern.</value> <value>Richte eine Entsperroption ein, um deine Aktion bei Tresor-Timeout zu ändern.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Für dein Konto ist die Duo Zwei-Faktor-Authentifizierung erforderlich. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Folge den Schritten von Duo, um die Anmeldung abzuschließen.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Duo starten</value>
</data>
</root> </root>

View File

@@ -2820,7 +2820,7 @@
<value>Συνέχεια στην επικοινωνία με την υποστήριξη;</value> <value>Συνέχεια στην επικοινωνία με την υποστήριξη;</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve"> <data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value> <value>Συνέχεια στην πολιτική απορρήτου;</value>
</data> </data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Συνέχεια στο κατάστημα εφαρμογών;</value> <value>Συνέχεια στο κατάστημα εφαρμογών;</value>
@@ -2842,7 +2842,7 @@
<value>Δεν μπορείτε να βρείτε αυτό που ψάχνετε; Επικοινωνήστε με την υποστήριξη Bitwarden στο bitwarden.com.</value> <value>Δεν μπορείτε να βρείτε αυτό που ψάχνετε; Επικοινωνήστε με την υποστήριξη Bitwarden στο bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve"> <data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value> <value>Δείτε την πολιτική απορρήτου μας στο bitwarden.com.</value>
</data> </data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Εξερευνήστε περισσότερες δυνατότητες του Bitwarden λογαριασμού σας, στην εφαρμογή διαδικτύου.</value> <value>Εξερευνήστε περισσότερες δυνατότητες του Bitwarden λογαριασμού σας, στην εφαρμογή διαδικτύου.</value>
@@ -2875,4 +2875,13 @@
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Ρυθμίστε μια επιλογή κλειδώματος για να αλλάξετε την ενέργεια στη λήξη χρόνου του vault σας.</value> <value>Ρυθμίστε μια επιλογή κλειδώματος για να αλλάξετε την ενέργεια στη λήξη χρόνου του vault σας.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2876,4 +2876,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2890,4 +2890,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2878,4 +2878,13 @@ seleccione Agregar TOTP para almacenar la clave de forma segura</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Configura una opción de desbloqueo para cambiar tu acción de tiempo de espera de tu caja fuerte.</value> <value>Configura una opción de desbloqueo para cambiar tu acción de tiempo de espera de tu caja fuerte.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2876,4 +2876,13 @@ Soovid selle konto peale lülituda?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2875,4 +2875,13 @@ Kontu honetara aldatu nahi duzu?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Haluatko vaihtaa tähän tiliin?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Muuta holvisi aikakatkaisutoimintoa määrittämällä lukituksen avaustapa.</value> <value>Muuta holvisi aikakatkaisutoimintoa määrittämällä lukituksen avaustapa.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Tilillesi kirjautuminen vaatii Duo-vahvistuksen.</value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Viimeistele kirjautuminen seuraamalla Duon ohjeita.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Avaa Duo</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Gusto mo bang pumunta sa account na ito?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Voulez-vous basculer vers ce compte ?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Configurez une méthode de déverrouillage pour modifier l'action après délai d'expiration de votre coffre.</value> <value>Configurez une méthode de déverrouillage pour modifier l'action après délai d'expiration de votre coffre.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2879,4 +2879,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2876,4 +2876,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2874,4 +2874,13 @@
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Za promjenu vremena isteka trezora, odredi način otključavanja.</value> <value>Za promjenu vremena isteka trezora, odredi način otključavanja.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2875,4 +2875,13 @@ Szeretnénk átváltani erre a fiókra?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Állítsunk be egy feloldási módot a széf időkifutási műveletének módosításához.</value> <value>Állítsunk be egy feloldási módot a széf időkifutási műveletének módosításához.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>DUO kétlépéses bejelentkezés szükséges a fiókhoz. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Kövessük a Duo lépéseit a bejelentkezés befejezéséhez.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Duo indítása</value>
</data>
</root> </root>

View File

@@ -2876,4 +2876,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -172,7 +172,7 @@
<comment>Message shown when interacting with the server</comment> <comment>Message shown when interacting with the server</comment>
</data> </data>
<data name="DoYouReallyWantToDelete" xml:space="preserve"> <data name="DoYouReallyWantToDelete" xml:space="preserve">
<value>Vuoi davvero eliminarlo? Questa operazione non può essere annullata.</value> <value>Sei sicuro di volerlo eliminare? Questa operazione è irreversibile.</value>
<comment>Confirmation alert message when deleteing something.</comment> <comment>Confirmation alert message when deleteing something.</comment>
</data> </data>
<data name="Edit" xml:space="preserve"> <data name="Edit" xml:space="preserve">
@@ -193,10 +193,10 @@
<value>Contattaci</value> <value>Contattaci</value>
</data> </data>
<data name="EmailUsDescription" xml:space="preserve"> <data name="EmailUsDescription" xml:space="preserve">
<value>Mandaci un'email per ottenere aiuto o lasciare un feedback</value> <value>Inviaci un'email per ottenere aiuto o lasciare un feedback.</value>
</data> </data>
<data name="EnterPIN" xml:space="preserve"> <data name="EnterPIN" xml:space="preserve">
<value>Digita il tuo PIN.</value> <value>Inserisci il tuo PIN.</value>
</data> </data>
<data name="Favorites" xml:space="preserve"> <data name="Favorites" xml:space="preserve">
<value>Preferiti</value> <value>Preferiti</value>
@@ -2876,4 +2876,13 @@ Vuoi passare a questo account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Imposta un metodo di sblocco per modificare l'azione timeout cassaforte.</value> <value>Imposta un metodo di sblocco per modificare l'azione timeout cassaforte.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2876,4 +2876,13 @@
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>保管庫のタイムアウト動作を変更するには、ロック解除方法を設定してください。</value> <value>保管庫のタイムアウト動作を変更するには、ロック解除方法を設定してください。</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>アカウントには Duo 二段階認証が必要です。</value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Duo の手順に従ってログインを完了してください。</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Duo を起動</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2876,4 +2876,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Ar norite pereiti prie šios paskyros?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -172,7 +172,7 @@
<comment>Message shown when interacting with the server</comment> <comment>Message shown when interacting with the server</comment>
</data> </data>
<data name="DoYouReallyWantToDelete" xml:space="preserve"> <data name="DoYouReallyWantToDelete" xml:space="preserve">
<value>Vai jūs tiešām vēlaties dzēst? Šo darbību nav iespējams atsaukt.</value> <value>Vai tiešām izdzēst? To nevar atsaukt.</value>
<comment>Confirmation alert message when deleteing something.</comment> <comment>Confirmation alert message when deleteing something.</comment>
</data> </data>
<data name="Edit" xml:space="preserve"> <data name="Edit" xml:space="preserve">
@@ -193,10 +193,10 @@
<value>Nosūtīt mums e-pasta ziņu</value> <value>Nosūtīt mums e-pasta ziņu</value>
</data> </data>
<data name="EmailUsDescription" xml:space="preserve"> <data name="EmailUsDescription" xml:space="preserve">
<value>Sūti mums e-pasta ziņu, lai saņemtu palīdzību vai sniegtu atsauksmes!</value> <value>Nosūtīt mums e-pasta ziņu, lai saņemtu palīdzību vai sniegtu atsauksmes.</value>
</data> </data>
<data name="EnterPIN" xml:space="preserve"> <data name="EnterPIN" xml:space="preserve">
<value>Ievadīt PIN kodu.</value> <value>Jāievada PIN kods.</value>
</data> </data>
<data name="Favorites" xml:space="preserve"> <data name="Favorites" xml:space="preserve">
<value>Izlase</value> <value>Izlase</value>
@@ -232,7 +232,7 @@
<value>Mape atjaunota.</value> <value>Mape atjaunota.</value>
</data> </data>
<data name="GoToWebsite" xml:space="preserve"> <data name="GoToWebsite" xml:space="preserve">
<value>Doties uz tīmekļa vietni</value> <value>Doties uz tīmekļvietni</value>
<comment>The button text that allows user to launch the website to their web browser.</comment> <comment>The button text that allows user to launch the website to their web browser.</comment>
</data> </data>
<data name="HelpAndFeedback" xml:space="preserve"> <data name="HelpAndFeedback" xml:space="preserve">
@@ -243,18 +243,18 @@
<comment>Hide a secret value that is currently shown (password).</comment> <comment>Hide a secret value that is currently shown (password).</comment>
</data> </data>
<data name="InternetConnectionRequiredMessage" xml:space="preserve"> <data name="InternetConnectionRequiredMessage" xml:space="preserve">
<value>Lūgums izveidot savienojumu ar tīmekli, lai varētu turpināt.</value> <value>Lūgums izveidot savienojumu ar internetu, lai varētu turpināt.</value>
<comment>Description message for the alert when internet connection is required to continue.</comment> <comment>Description message for the alert when internet connection is required to continue.</comment>
</data> </data>
<data name="InternetConnectionRequiredTitle" xml:space="preserve"> <data name="InternetConnectionRequiredTitle" xml:space="preserve">
<value>Nepieciešams tīmekļa savienojums</value> <value>Nepieciešams interneta savienojums</value>
<comment>Title for the alert when internet connection is required to continue.</comment> <comment>Title for the alert when internet connection is required to continue.</comment>
</data> </data>
<data name="InvalidMasterPassword" xml:space="preserve"> <data name="InvalidMasterPassword" xml:space="preserve">
<value>Nederīga galvenā parole. Mēģini vēlreiz!</value> <value>Nederīga galvenā parole. Jāmēģina vēlreiz.</value>
</data> </data>
<data name="InvalidPIN" xml:space="preserve"> <data name="InvalidPIN" xml:space="preserve">
<value>Nederīgs PIN. Mēģini vēlreiz!</value> <value>Nederīgs PIN. Jāmēģina vēlreiz.</value>
</data> </data>
<data name="Launch" xml:space="preserve"> <data name="Launch" xml:space="preserve">
<value>Palaist</value> <value>Palaist</value>
@@ -394,10 +394,10 @@
<value>Skatīt</value> <value>Skatīt</value>
</data> </data>
<data name="VisitOurWebsite" xml:space="preserve"> <data name="VisitOurWebsite" xml:space="preserve">
<value>Apmeklēt mūsu tīmekļa vietni</value> <value>Apmeklēt mūsu tīmekļvietni</value>
</data> </data>
<data name="Website" xml:space="preserve"> <data name="Website" xml:space="preserve">
<value>Tīmekļa vietne</value> <value>Tīmekļvietne</value>
<comment>Label for a website.</comment> <comment>Label for a website.</comment>
</data> </data>
<data name="Yes" xml:space="preserve"> <data name="Yes" xml:space="preserve">
@@ -419,7 +419,7 @@
<value>Izmantot Bitwarden pieejamības pakalpojumu, lai automātiski aizpildītu pieteikšanās veidnes dažādās lietotnēs un tīmeklī.</value> <value>Izmantot Bitwarden pieejamības pakalpojumu, lai automātiski aizpildītu pieteikšanās veidnes dažādās lietotnēs un tīmeklī.</value>
</data> </data>
<data name="AutofillService" xml:space="preserve"> <data name="AutofillService" xml:space="preserve">
<value>Automātiskā aizpilde</value> <value>Automātiskās aizpildes pakalpojums</value>
</data> </data>
<data name="AvoidAmbiguousCharacters" xml:space="preserve"> <data name="AvoidAmbiguousCharacters" xml:space="preserve">
<value>Izvairīties no viegli sajaucamām rakstzīmēm</value> <value>Izvairīties no viegli sajaucamām rakstzīmēm</value>
@@ -434,7 +434,7 @@
<value>Izmantot Bitwarden Safari un citās lietotnēs, lai automātiski ievadītu pieteikšanās vienumus.</value> <value>Izmantot Bitwarden Safari un citās lietotnēs, lai automātiski ievadītu pieteikšanās vienumus.</value>
</data> </data>
<data name="BitwardenAutofillService" xml:space="preserve"> <data name="BitwardenAutofillService" xml:space="preserve">
<value>Bitwarden automātiskā aizpilde</value> <value>Bitwarden automātiskās aizpildes pakalpojums</value>
</data> </data>
<data name="BitwardenAutofillAccessibilityServiceDescription" xml:space="preserve"> <data name="BitwardenAutofillAccessibilityServiceDescription" xml:space="preserve">
<value>Izmantot Bitwarden pieejamības pakalpojumu, lai automātiski aizpildītu pieteikšanās veidnes.</value> <value>Izmantot Bitwarden pieejamības pakalpojumu, lai automātiski aizpildītu pieteikšanās veidnes.</value>
@@ -443,7 +443,7 @@
<value>Mainīt e-pasta adresi</value> <value>Mainīt e-pasta adresi</value>
</data> </data>
<data name="ChangeEmailConfirmation" xml:space="preserve"> <data name="ChangeEmailConfirmation" xml:space="preserve">
<value>E-pasta adresi ir iespējams nomainīt bitwarden.com tīmekļa glabātavā. Vai apmeklēt tīmekļa vietni?</value> <value>E-pasta adresi ir iespējams nomainīt bitwarden.com tīmekļa glabātavā. Vai tagad apmeklēt tīmekļvietni?</value>
</data> </data>
<data name="ChangeMasterPassword" xml:space="preserve"> <data name="ChangeMasterPassword" xml:space="preserve">
<value>Mainīt galveno paroli</value> <value>Mainīt galveno paroli</value>
@@ -517,7 +517,7 @@
<value>Ievietot vienumus</value> <value>Ievietot vienumus</value>
</data> </data>
<data name="ImportItemsConfirmation" xml:space="preserve"> <data name="ImportItemsConfirmation" xml:space="preserve">
<value>Daudzu vienumu ievietošanu var veikt bitwarden.com tīmekļa glabātavā. Vai apmeklēt tīmekļa vietni?</value> <value>Daudzu vienumu ievietošanu var veikt bitwarden.com tīmekļa glabātavā. Vai tagad apmeklēt tīmekļvietni?</value>
</data> </data>
<data name="ImportItemsDescription" xml:space="preserve"> <data name="ImportItemsDescription" xml:space="preserve">
<value>Ātri ievietot daudzus vienumus no citām paroļu pārvaldības lietotnēm.</value> <value>Ātri ievietot daudzus vienumus no citām paroļu pārvaldības lietotnēm.</value>
@@ -607,7 +607,7 @@
<value>Glabātavā nav vienumu.</value> <value>Glabātavā nav vienumu.</value>
</data> </data>
<data name="NoItemsTap" xml:space="preserve"> <data name="NoItemsTap" xml:space="preserve">
<value>Glabātāvā nav vienumu, ko izmantot šajā tīmekļa vietnē/lietotnē. Piesist, lai pievienotu.</value> <value>Glabātāvā nav vienumu, ko izmantot šajā tīmekļvietnē/lietotnē. Piesist, lai pievienotu.</value>
</data> </data>
<data name="NoUsernamePasswordConfigured" xml:space="preserve"> <data name="NoUsernamePasswordConfigured" xml:space="preserve">
<value>Šajā pieteikšanās vienumā nav norādīts lietotājvārds vai parole.</value> <value>Šajā pieteikšanās vienumā nav norādīts lietotājvārds vai parole.</value>
@@ -748,7 +748,7 @@
<value>Kad tiek atlasīts ievades lauks un parādās Bitwarden automātiskās aizpildes lodziņš, jāpiesit tam, lai palaistu automātiskās aizpildes pakalpojumu.</value> <value>Kad tiek atlasīts ievades lauks un parādās Bitwarden automātiskās aizpildes lodziņš, jāpiesit tam, lai palaistu automātiskās aizpildes pakalpojumu.</value>
</data> </data>
<data name="BitwardenAutofillServiceNotificationContent" xml:space="preserve"> <data name="BitwardenAutofillServiceNotificationContent" xml:space="preserve">
<value>Piesist šim paziņojumam, lai automātiski aizpildītu, izmantojot vienumu no glabātavas.</value> <value>Jāpiesit šim paziņojumam, lai automātiski aizpildītu ar vienumu no glabātavas.</value>
</data> </data>
<data name="BitwardenAutofillServiceOpenAccessibilitySettings" xml:space="preserve"> <data name="BitwardenAutofillServiceOpenAccessibilitySettings" xml:space="preserve">
<value>Atvērt pieejamības iestatījumus</value> <value>Atvērt pieejamības iestatījumus</value>
@@ -775,7 +775,7 @@
<value>Stāvoklis</value> <value>Stāvoklis</value>
</data> </data>
<data name="BitwardenAutofillServiceAlert2" xml:space="preserve"> <data name="BitwardenAutofillServiceAlert2" xml:space="preserve">
<value>Vieglākais veids, kā glabātavā pievienot jaunus pieteikšanās vienumus, ir no Bitwarden automātiskās aizpildes pakalpojuma. Vairāk par Bitwarden automātiskās aizpildi var uzzināt iestatījumu skatā.</value> <value>Vieglākais veids, kā glabātavā pievienot jaunus pieteikšanās vienumus, ir ar Bitwarden automātiskās aizpildes pakalpojumu. Vairāk par Bitwarden automātisko aizpildi var uzzināt iestatījumu skatā.</value>
</data> </data>
<data name="Autofill" xml:space="preserve"> <data name="Autofill" xml:space="preserve">
<value>Automātiskā aizpilde</value> <value>Automātiskā aizpilde</value>
@@ -1134,7 +1134,7 @@ Nolasīšana notiks automātiski.</value>
<value>Derīgums</value> <value>Derīgums</value>
</data> </data>
<data name="ShowWebsiteIcons" xml:space="preserve"> <data name="ShowWebsiteIcons" xml:space="preserve">
<value>Rādīt vietņu ikonas</value> <value>Rādīt tīmekļvietņu ikonas</value>
</data> </data>
<data name="ShowWebsiteIconsDescription" xml:space="preserve"> <data name="ShowWebsiteIconsDescription" xml:space="preserve">
<value>Attēlot atpazīstamu attēlu pie katra pieteikšanās vienuma.</value> <value>Attēlot atpazīstamu attēlu pie katra pieteikšanās vienuma.</value>
@@ -1143,7 +1143,7 @@ Nolasīšana notiks automātiski.</value>
<value>Ikonu servera URL</value> <value>Ikonu servera URL</value>
</data> </data>
<data name="AutofillWithBitwarden" xml:space="preserve"> <data name="AutofillWithBitwarden" xml:space="preserve">
<value>Automātiskā aizpilde ar Bitwarden</value> <value>Automātiski aizpildīt ar Bitwarden</value>
</data> </data>
<data name="VaultIsLocked" xml:space="preserve"> <data name="VaultIsLocked" xml:space="preserve">
<value>Glabātava ir slēgta</value> <value>Glabātava ir slēgta</value>
@@ -1170,7 +1170,7 @@ Nolasīšana notiks automātiski.</value>
<value>Bitwarden automātiskās aizpildes pakalpojums izmanto Android automātiskās aizpildes ietvaru, lai palīdzētu aizpildīt pieteikšanās, kredītkartes, un identitātes informācijas veidnes citās ierīces lietotnēs.</value> <value>Bitwarden automātiskās aizpildes pakalpojums izmanto Android automātiskās aizpildes ietvaru, lai palīdzētu aizpildīt pieteikšanās, kredītkartes, un identitātes informācijas veidnes citās ierīces lietotnēs.</value>
</data> </data>
<data name="BitwardenAutofillServiceDescription" xml:space="preserve"> <data name="BitwardenAutofillServiceDescription" xml:space="preserve">
<value>Bitwarden automātiskās aizpilde tiek izmantota, lai aizpildītu pieteikšanās, kredītkaršu un identitātes informācijas veidnes citās lietotnēs.</value> <value>Bitwarden automātiskā aizpilde ir izmantojama, lai aizpildītu pieteikšanās, kredītkaršu un identitātes informācijas veidnes citās lietotnēs.</value>
</data> </data>
<data name="BitwardenAutofillServiceOpenAutofillSettings" xml:space="preserve"> <data name="BitwardenAutofillServiceOpenAutofillSettings" xml:space="preserve">
<value>Atvērt automātiskās aizpildes iestatījumus</value> <value>Atvērt automātiskās aizpildes iestatījumus</value>
@@ -1289,7 +1289,7 @@ Nolasīšana notiks automātiski.</value>
<value>Vispirms ir jāpiesakās galvenajā Bitwarden lietotnē, lai varētu izmantot automātisko aizpildi.</value> <value>Vispirms ir jāpiesakās galvenajā Bitwarden lietotnē, lai varētu izmantot automātisko aizpildi.</value>
</data> </data>
<data name="AutofillSetup" xml:space="preserve"> <data name="AutofillSetup" xml:space="preserve">
<value>Pieteikšanāš vienumi tagad ir viegli pieejami tastatūrā, kad notiek pieteikšanās lietotnēs un tīmekļa vietnēs.</value> <value>Pieteikšanās vienumi tagad ir viegli pieejami tastatūrā, kad notiek pieteikšanās lietotnēs un tīmekļvietnēs.</value>
</data> </data>
<data name="AutofillSetup2" xml:space="preserve"> <data name="AutofillSetup2" xml:space="preserve">
<value>Mēs iesakām atspējot jebkuras citas automātiskās aizpildes lietotnes iestatījumos, ja nav iecerēts izmantot tās.</value> <value>Mēs iesakām atspējot jebkuras citas automātiskās aizpildes lietotnes iestatījumos, ja nav iecerēts izmantot tās.</value>
@@ -1462,7 +1462,7 @@ Nolasīšana notiks automātiski.</value>
<comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment> <comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment>
</data> </data>
<data name="LearnOrgConfirmation" xml:space="preserve"> <data name="LearnOrgConfirmation" xml:space="preserve">
<value>Bitwarden nodrošina iespēju kopīgot glabātavas vienumus ar citiem, kad tiek izmantots apvienības konts. Vai apmeklēt bitwarden.com tīmekļa vietni, lai uzzinātu vairāk?</value> <value>Bitwarden nodrošina iespēju kopīgot glabātavas vienumus ar citiem, kad tiek izmantots apvienības konts. Vai apmeklēt bitwarden.com tīmekļvietni, lai uzzinātu vairāk?</value>
</data> </data>
<data name="ExportVault" xml:space="preserve"> <data name="ExportVault" xml:space="preserve">
<value>Izgūt glabātavas saturu</value> <value>Izgūt glabātavas saturu</value>
@@ -1586,7 +1586,7 @@ Nolasīšana notiks automātiski.</value>
<value>Pārsāknējot lietotni</value> <value>Pārsāknējot lietotni</value>
</data> </data>
<data name="AutofillServiceNotEnabled" xml:space="preserve"> <data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>Automātiskā aizpilde padara drošu piekļuvi Bitwarden galbātavai vienkāršu no citām 0tīmekļa vietnēm un lietotnēm. Izskatās, ka nav iespējota Bitwarden automātiskā aizpilde. To var izdarīt iestatījumu sadaļā.</value> <value>Automātiskā aizpildīšana padara drošu piekļuvi Bitwarden galbātavai vienkāršu no citām tīmekļvietnēm un lietotnēm. Izskatās, ka nav iespējota Bitwarden automātiskā aizpildīšana. To var izdarīt iestatījumu sadaļā.</value>
</data> </data>
<data name="ThemeAppliedOnRestart" xml:space="preserve"> <data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Izskata izmaiņas tiks pielietotas pēc lietotnes pārsāknēšanas.</value> <value>Izskata izmaiņas tiks pielietotas pēc lietotnes pārsāknēšanas.</value>
@@ -1729,7 +1729,7 @@ Nolasīšana notiks automātiski.</value>
<comment>(action prompt) Label for the search text field when viewing the trash folder</comment> <comment>(action prompt) Label for the search text field when viewing the trash folder</comment>
</data> </data>
<data name="DoYouReallyWantToPermanentlyDeleteCipher" xml:space="preserve"> <data name="DoYouReallyWantToPermanentlyDeleteCipher" xml:space="preserve">
<value>Vai tiešām vēlaties neatgriezeniski dzēst? To nevar atsaukt.</value> <value>Vai tiešām neatgriezeniski izdzēst? To nevar atsaukt.</value>
<comment>Confirmation alert message when permanently deleteing a cipher.</comment> <comment>Confirmation alert message when permanently deleteing a cipher.</comment>
</data> </data>
<data name="DoYouReallyWantToRestoreCipher" xml:space="preserve"> <data name="DoYouReallyWantToRestoreCipher" xml:space="preserve">
@@ -2213,7 +2213,7 @@ Nolasīšana notiks automātiski.</value>
<value>Atgadījās kļūda, kad apliecinājuma kods tika sūtīts uz e-pastu. Lūgums mēģināt vēlreiz</value> <value>Atgadījās kļūda, kad apliecinājuma kods tika sūtīts uz e-pastu. Lūgums mēģināt vēlreiz</value>
</data> </data>
<data name="EnterTheVerificationCodeThatWasSentToYourEmail" xml:space="preserve"> <data name="EnterTheVerificationCodeThatWasSentToYourEmail" xml:space="preserve">
<value>Ievadīt pārbaudes kodu, kas tika nosūtīts e-pastā</value> <value>Jāievada apliecinājuma kods, kas tika nosūtīts e-pastā</value>
</data> </data>
<data name="SubmitCrashLogs" xml:space="preserve"> <data name="SubmitCrashLogs" xml:space="preserve">
<value>Iesniegt avāriju ierakstus</value> <value>Iesniegt avāriju ierakstus</value>
@@ -2442,7 +2442,7 @@ jāizvēlas "Pievienot TOTP", lai droši glabātu atslēgu.</value>
<value>E-pasta veids</value> <value>E-pasta veids</value>
</data> </data>
<data name="WebsiteRequired" xml:space="preserve"> <data name="WebsiteRequired" xml:space="preserve">
<value>Mājaslapa (nepieciešama)</value> <value>Tīmekļviente (nepieciešama)</value>
</data> </data>
<data name="UnknownXErrorMessage" xml:space="preserve"> <data name="UnknownXErrorMessage" xml:space="preserve">
<value>Notika nezināma kļūda {0}.</value> <value>Notika nezināma kļūda {0}.</value>
@@ -2466,7 +2466,7 @@ jāizvēlas "Pievienot TOTP", lai droši glabātu atslēgu.</value>
<value>Pieejamības pakalpojuma izmantošanas skaidrojums</value> <value>Pieejamības pakalpojuma izmantošanas skaidrojums</value>
</data> </data>
<data name="AccessibilityDisclosureText" xml:space="preserve"> <data name="AccessibilityDisclosureText" xml:space="preserve">
<value>Bitwarden izmanto pieejamības pakalpojumu, lai meklētu pieteikšanās laukus lietotnēs un tīmekļa vietnēs, tad noskaidro atbistošus lauku identifikatorus lietotājvārda un paroles ievadīšanai, kad ir atrasta atbilstība lietotnei vai vietnei. Bitwarden neglabā neko no informācijas, ko nodrošina pakalpojums, kā arī nemēģina pārvaldīt ekrānā redzamās daļas, kas nav saistītas ar pieteikšanās datu ievadi.</value> <value>Bitwarden izmanto pieejamības pakalpojumu, lai meklētu pieteikšanās laukus lietotnēs un tīmekļvietnēs, tad noskaidro atbistošus lauku identifikatorus lietotājvārda un paroles ievadīšanai, kad ir atrasta atbilstība lietotnei vai vietnei. Bitwarden neglabā neko no informācijas, ko nodrošina pakalpojums, kā arī nemēģina pārvaldīt ekrānā redzamās daļas, kas nav saistītas ar pieteikšanās datu ievadi.</value>
</data> </data>
<data name="Accept" xml:space="preserve"> <data name="Accept" xml:space="preserve">
<value>Pieņemt</value> <value>Pieņemt</value>
@@ -2850,7 +2850,7 @@ Vai pārslēgties uz šo kontu?</value>
<value>Vairāk sava Bitwarden konta iespēju var izpētīt tīmekļa vietnē.</value> <value>Vairāk sava Bitwarden konta iespēju var izpētīt tīmekļa vietnē.</value>
</data> </data>
<data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve"> <data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve">
<value>Bitwarden nodrošina iespēju kopīgot savas glabātavas vienumus ar citiem, kad tiek izmantota apvienība. Vairāk var uzzināt bitwarden.com tīmekļa vietnē.</value> <value>Bitwarden nodrošina iespēju kopīgot savas glabātavas vienumus ar citiem, kad tiek izmantota apvienība. Vairāk var uzzināt bitwarden.com tīmekļvietnē.</value>
</data> </data>
<data name="RateAppDescriptionLong" xml:space="preserve"> <data name="RateAppDescriptionLong" xml:space="preserve">
<value>Var palīdzēt citiem noskaidrot, vai Bitwarden tiem der. To var izdarīt lietotņu veikalā, atstājot vērtējumu.</value> <value>Var palīdzēt citiem noskaidrot, vai Bitwarden tiem der. To var izdarīt lietotņu veikalā, atstājot vērtējumu.</value>
@@ -2877,4 +2877,13 @@ Vai pārslēgties uz šo kontu?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Jāuzstāda atslēgšanas iespēja, lai mainītu glabātavas noildzes darbību.</value> <value>Jāuzstāda atslēgšanas iespēja, lai mainītu glabātavas noildzes darbību.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Kontam ir nepieciešama Duo divpakāpju pieteikšanās. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Jāseko Duo norādēm, lai pabeigtu pieteikšanos.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Palaist Duo</value>
</data>
</root> </root>

View File

@@ -2876,4 +2876,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Vil du bytte til denne kontoen?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2876,4 +2876,13 @@ Wilt u naar dit account wisselen?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Stel een ontgrendelingsmethode in om je kluis time-out actie te wijzigen.</value> <value>Stel een ontgrendelingsmethode in om je kluis time-out actie te wijzigen.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Jouw account vereist Duo-tweestapsaanmelding. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Volg de stappen van Duo om in te loggen.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Duo starten</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2877,4 +2877,13 @@ Do you want to switch to this account?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Set up an unlock option to change your vault timeout action.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data>
</root> </root>

View File

@@ -2876,4 +2876,13 @@ Czy chcesz przełączyć się na to konto?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Ustaw opcje odblokowania, aby zmienić czas blokowania sejfu.</value> <value>Ustaw opcje odblokowania, aby zmienić czas blokowania sejfu.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Dwustopniowe logowanie Duo jest wymagane dla Twojego konta. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Wykonaj kroki od Duo, aby zakończyć logowanie.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Uruchom Duo</value>
</data>
</root> </root>

View File

@@ -2822,16 +2822,16 @@ Você deseja mudar para esta conta?</value>
<value>Continuar e contatar o suporte?</value> <value>Continuar e contatar o suporte?</value>
</data> </data>
<data name="ContinueToPrivacyPolicy" xml:space="preserve"> <data name="ContinueToPrivacyPolicy" xml:space="preserve">
<value>Continue to privacy policy?</value> <value>Continuar para a política de privacidade?</value>
</data> </data>
<data name="ContinueToAppStore" xml:space="preserve"> <data name="ContinueToAppStore" xml:space="preserve">
<value>Continuar para a loja de apps?</value> <value>Continuar para a loja de apps?</value>
</data> </data>
<data name="TwoStepLoginDescriptionLong" xml:space="preserve"> <data name="TwoStepLoginDescriptionLong" xml:space="preserve">
<value>Make your account more secure by setting up two-step login in the Bitwarden web app.</value> <value>Torne sua conta mais segura configurando o login em duas etapas no aplicativo web do Bitwarden.</value>
</data> </data>
<data name="ChangeMasterPasswordDescriptionLong" xml:space="preserve"> <data name="ChangeMasterPasswordDescriptionLong" xml:space="preserve">
<value>You can change your master password on the Bitwarden web app.</value> <value>Você pode alterar a sua senha mestra no aplicativo web Bitwarden.</value>
</data> </data>
<data name="YouCanImportDataToYourVaultOnX" xml:space="preserve"> <data name="YouCanImportDataToYourVaultOnX" xml:space="preserve">
<value>Você pode importar dados para o seu cofre no {0}.</value> <value>Você pode importar dados para o seu cofre no {0}.</value>
@@ -2841,19 +2841,19 @@ Você deseja mudar para esta conta?</value>
<value>Saiba mais sobre como usar o Bitwarden no centro de ajuda.</value> <value>Saiba mais sobre como usar o Bitwarden no centro de ajuda.</value>
</data> </data>
<data name="ContactSupportDescriptionLong" xml:space="preserve"> <data name="ContactSupportDescriptionLong" xml:space="preserve">
<value>Cant find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value> <value>Não encontrou o que está procurando? Entre em contato com o suporte do Bitwarden em bitwarden.com.</value>
</data> </data>
<data name="PrivacyPolicyDescriptionLong" xml:space="preserve"> <data name="PrivacyPolicyDescriptionLong" xml:space="preserve">
<value>Check out our privacy policy on bitwarden.com.</value> <value>Confira a nossa política de privacidade em bitwarden.com.</value>
</data> </data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore more features of your Bitwarden account on the web app.</value> <value>Explore mais recursos da sua conta no Bitwarden no aplicativo web.</value>
</data> </data>
<data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve"> <data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve">
<value>Bitwarden allows you to share your vault items with others by using an organization. Learn more on the bitwarden.com website.</value> <value>O Bitwarden permite compartilhar os seus itens do cofre com outros ao utilizar uma organização. Gostaria de visitar o site bitwarden.com para saber mais?</value>
</data> </data>
<data name="RateAppDescriptionLong" xml:space="preserve"> <data name="RateAppDescriptionLong" xml:space="preserve">
<value>Help others find out if Bitwarden is right for them. Visit the app store and leave a rating now.</value> <value>Ajude outros a descobrir se o Bitwarden é adequado para eles. Visite a loja de aplicativos e deixe uma avaliação agora.</value>
</data> </data>
<data name="DefaultDarkThemeDescriptionLong" xml:space="preserve"> <data name="DefaultDarkThemeDescriptionLong" xml:space="preserve">
<value>Usar o tema escuro quando o modo escuro do seu dispositivo estiver ativado</value> <value>Usar o tema escuro quando o modo escuro do seu dispositivo estiver ativado</value>
@@ -2869,12 +2869,21 @@ Você deseja mudar para esta conta?</value>
<value>Conta desconectada.</value> <value>Conta desconectada.</value>
</data> </data>
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve"> <data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
<value>Your organization permissions were updated, requiring you to set a master password.</value> <value>As permissões da sua organização foram atualizadas, exigindo que você defina uma senha mestra.</value>
</data> </data>
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve"> <data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
<value>Your organization requires you to set a master password.</value> <value>Sua organização requer que você defina uma senha mestra.</value>
</data> </data>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Set up an unlock option to change your vault timeout action.</value> <value>Configure um método de desbloqueio para alterar o tempo limite do cofre.</value>
</data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>Duo two-step login is required for your account. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Follow the steps from Duo to finish logging in.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Launch Duo</value>
</data> </data>
</root> </root>

View File

@@ -172,7 +172,7 @@
<comment>Message shown when interacting with the server</comment> <comment>Message shown when interacting with the server</comment>
</data> </data>
<data name="DoYouReallyWantToDelete" xml:space="preserve"> <data name="DoYouReallyWantToDelete" xml:space="preserve">
<value>Pretende mesmo eliminar? Isto não pode ser anulado.</value> <value>Pretende mesmo eliminar? Esta ação não pode ser anulada.</value>
<comment>Confirmation alert message when deleteing something.</comment> <comment>Confirmation alert message when deleteing something.</comment>
</data> </data>
<data name="Edit" xml:space="preserve"> <data name="Edit" xml:space="preserve">
@@ -193,7 +193,7 @@
<value>Enviar-nos um e-mail</value> <value>Enviar-nos um e-mail</value>
</data> </data>
<data name="EmailUsDescription" xml:space="preserve"> <data name="EmailUsDescription" xml:space="preserve">
<value>Envie-nos um e-mail diretamente para obter ajuda ou deixar feedback.</value> <value>Envie-nos um e-mail diretamente para obter ajuda ou dar feedback.</value>
</data> </data>
<data name="EnterPIN" xml:space="preserve"> <data name="EnterPIN" xml:space="preserve">
<value>Introduza o seu código PIN.</value> <value>Introduza o seu código PIN.</value>
@@ -206,7 +206,7 @@
<value>Apresentar um relatório de erros</value> <value>Apresentar um relatório de erros</value>
</data> </data>
<data name="FileBugReportDescription" xml:space="preserve"> <data name="FileBugReportDescription" xml:space="preserve">
<value>Abrir um issue no nosso repositório do GitHub.</value> <value>Abra um problema no nosso repositório do GitHub.</value>
</data> </data>
<data name="FingerprintDirection" xml:space="preserve"> <data name="FingerprintDirection" xml:space="preserve">
<value>Utilize a sua impressão digital para verificar.</value> <value>Utilize a sua impressão digital para verificar.</value>
@@ -443,7 +443,7 @@
<value>Alterar e-mail</value> <value>Alterar e-mail</value>
</data> </data>
<data name="ChangeEmailConfirmation" xml:space="preserve"> <data name="ChangeEmailConfirmation" xml:space="preserve">
<value>Pode alterar o seu endereço de e-mail no cofre do site bitwarden.com. Deseja visitar o site agora?</value> <value>Pode alterar o seu endereço de e-mail no cofre do site bitwarden.com. Pretende visitar o site agora?</value>
</data> </data>
<data name="ChangeMasterPassword" xml:space="preserve"> <data name="ChangeMasterPassword" xml:space="preserve">
<value>Alterar palavra-passe mestra</value> <value>Alterar palavra-passe mestra</value>
@@ -511,13 +511,13 @@
<value>Gerar palavra-passe</value> <value>Gerar palavra-passe</value>
</data> </data>
<data name="GetPasswordHint" xml:space="preserve"> <data name="GetPasswordHint" xml:space="preserve">
<value>Obter dica da palavra-passe mestra</value> <value>Obter a dica da sua palavra-passe mestra</value>
</data> </data>
<data name="ImportItems" xml:space="preserve"> <data name="ImportItems" xml:space="preserve">
<value>Importar itens</value> <value>Importar itens</value>
</data> </data>
<data name="ImportItemsConfirmation" xml:space="preserve"> <data name="ImportItemsConfirmation" xml:space="preserve">
<value>Pode importar itens em massa do cofre do site bitwarden.com. Deseja visitar o site agora?</value> <value>Pode importar itens em massa do cofre do site bitwarden.com. Pretende visitar o site agora?</value>
</data> </data>
<data name="ImportItemsDescription" xml:space="preserve"> <data name="ImportItemsDescription" xml:space="preserve">
<value>Importe rapidamente e em massa os seus itens de outras aplicações de gestão de palavras-passe.</value> <value>Importe rapidamente e em massa os seus itens de outras aplicações de gestão de palavras-passe.</value>
@@ -613,7 +613,7 @@
<value>Esta credencial não tem um nome de utilizador ou palavra-passe configurados.</value> <value>Esta credencial não tem um nome de utilizador ou palavra-passe configurados.</value>
</data> </data>
<data name="OkGotIt" xml:space="preserve"> <data name="OkGotIt" xml:space="preserve">
<value>Ok, entendido!</value> <value>Ok, percebido!</value>
<comment>Confirmation, like "Ok, I understand it"</comment> <comment>Confirmation, like "Ok, I understand it"</comment>
</data> </data>
<data name="OptionDefaults" xml:space="preserve"> <data name="OptionDefaults" xml:space="preserve">
@@ -718,7 +718,7 @@
<value>Ver item</value> <value>Ver item</value>
</data> </data>
<data name="WebVault" xml:space="preserve"> <data name="WebVault" xml:space="preserve">
<value>Cofre web Bitwarden</value> <value>Cofre Web Bitwarden</value>
</data> </data>
<data name="Lost2FAApp" xml:space="preserve"> <data name="Lost2FAApp" xml:space="preserve">
<value>Perdeu a aplicação de autenticação?</value> <value>Perdeu a aplicação de autenticação?</value>
@@ -895,7 +895,7 @@
A leitura será efetuada automaticamente.</value> A leitura será efetuada automaticamente.</value>
</data> </data>
<data name="ScanQrTitle" xml:space="preserve"> <data name="ScanQrTitle" xml:space="preserve">
<value>Digitalizar código QR</value> <value>Ler código QR</value>
</data> </data>
<data name="Camera" xml:space="preserve"> <data name="Camera" xml:space="preserve">
<value>Câmara</value> <value>Câmara</value>
@@ -964,7 +964,7 @@ A leitura será efetuada automaticamente.</value>
<value>Os URLs de ambiente foram guardados.</value> <value>Os URLs de ambiente foram guardados.</value>
</data> </data>
<data name="FormattedIncorrectly" xml:space="preserve"> <data name="FormattedIncorrectly" xml:space="preserve">
<value>{0} não está formatado corretamente.</value> <value>{0} não está corretamente formatado.</value>
<comment>Validation error when something is not formatted correctly, such as a URL or email address.</comment> <comment>Validation error when something is not formatted correctly, such as a URL or email address.</comment>
</data> </data>
<data name="IdentityUrl" xml:space="preserve"> <data name="IdentityUrl" xml:space="preserve">
@@ -981,7 +981,7 @@ A leitura será efetuada automaticamente.</value>
<value>URL do servidor</value> <value>URL do servidor</value>
</data> </data>
<data name="WebVaultUrl" xml:space="preserve"> <data name="WebVaultUrl" xml:space="preserve">
<value>URL do servidor do cofre web</value> <value>URL do servidor do cofre Web</value>
</data> </data>
<data name="BitwardenAutofillServiceNotificationContentOld" xml:space="preserve"> <data name="BitwardenAutofillServiceNotificationContentOld" xml:space="preserve">
<value>Toque nesta notificação para ver itens do seu cofre.</value> <value>Toque nesta notificação para ver itens do seu cofre.</value>
@@ -1131,7 +1131,7 @@ A leitura será efetuada automaticamente.</value>
<value>Endereço</value> <value>Endereço</value>
</data> </data>
<data name="Expiration" xml:space="preserve"> <data name="Expiration" xml:space="preserve">
<value>Expiração</value> <value>Prazo de validade</value>
</data> </data>
<data name="ShowWebsiteIcons" xml:space="preserve"> <data name="ShowWebsiteIcons" xml:space="preserve">
<value>Mostrar ícones do site</value> <value>Mostrar ícones do site</value>
@@ -1201,7 +1201,7 @@ A leitura será efetuada automaticamente.</value>
<value>Booleano</value> <value>Booleano</value>
</data> </data>
<data name="FieldTypeHidden" xml:space="preserve"> <data name="FieldTypeHidden" xml:space="preserve">
<value>Ocultado</value> <value>Oculto</value>
</data> </data>
<data name="FieldTypeLinked" xml:space="preserve"> <data name="FieldTypeLinked" xml:space="preserve">
<value>Associado</value> <value>Associado</value>
@@ -1263,7 +1263,7 @@ A leitura será efetuada automaticamente.</value>
<comment>An entity of multiple related people (ex. a team or business organization).</comment> <comment>An entity of multiple related people (ex. a team or business organization).</comment>
</data> </data>
<data name="HoldYubikeyNearTop" xml:space="preserve"> <data name="HoldYubikeyNearTop" xml:space="preserve">
<value>Segure a sua Yubikey perto do topo do dispositivo.</value> <value>Segure a sua Yubikey perto da parte superior do dispositivo.</value>
</data> </data>
<data name="TryAgain" xml:space="preserve"> <data name="TryAgain" xml:space="preserve">
<value>Tentar novamente</value> <value>Tentar novamente</value>
@@ -1310,7 +1310,7 @@ A leitura será efetuada automaticamente.</value>
<value>3. Toque em "Autopreenchimento de palavras-passe"</value> <value>3. Toque em "Autopreenchimento de palavras-passe"</value>
</data> </data>
<data name="AutofillTurnOn4" xml:space="preserve"> <data name="AutofillTurnOn4" xml:space="preserve">
<value>4. Ligue o Autopreenchimento</value> <value>4. Ative o Autopreenchimento</value>
</data> </data>
<data name="AutofillTurnOn5" xml:space="preserve"> <data name="AutofillTurnOn5" xml:space="preserve">
<value>5. Selecione "Bitwarden"</value> <value>5. Selecione "Bitwarden"</value>
@@ -1369,10 +1369,10 @@ A leitura será efetuada automaticamente.</value>
<value>Tipos</value> <value>Tipos</value>
</data> </data>
<data name="NoPasswordsToList" xml:space="preserve"> <data name="NoPasswordsToList" xml:space="preserve">
<value>Nenhuma palavra-passe para listar.</value> <value>Não há palavras-passe a enumerar.</value>
</data> </data>
<data name="NoItemsToList" xml:space="preserve"> <data name="NoItemsToList" xml:space="preserve">
<value>Não existem itens para listar.</value> <value>Não há itens a enumerar.</value>
</data> </data>
<data name="SearchCollection" xml:space="preserve"> <data name="SearchCollection" xml:space="preserve">
<value>Procurar na coleção</value> <value>Procurar na coleção</value>
@@ -1406,7 +1406,7 @@ A leitura será efetuada automaticamente.</value>
<value>Quem é o proprietário deste item?</value> <value>Quem é o proprietário deste item?</value>
</data> </data>
<data name="NoCollectionsToList" xml:space="preserve"> <data name="NoCollectionsToList" xml:space="preserve">
<value>Não existem coleções para listar.</value> <value>Não coleções a enumerar.</value>
</data> </data>
<data name="MovedItemToOrg" xml:space="preserve"> <data name="MovedItemToOrg" xml:space="preserve">
<value>{0} movido para {1}.</value> <value>{0} movido para {1}.</value>
@@ -1428,7 +1428,7 @@ A leitura será efetuada automaticamente.</value>
<value>Mover para organização</value> <value>Mover para organização</value>
</data> </data>
<data name="NoOrgsToList" xml:space="preserve"> <data name="NoOrgsToList" xml:space="preserve">
<value>Nenhuma organização para listar.</value> <value>Não há organizações a enumerar.</value>
</data> </data>
<data name="MoveToOrgDesc" xml:space="preserve"> <data name="MoveToOrgDesc" xml:space="preserve">
<value>Escolha uma organização para a qual pretende mover este item. Mover para uma organização transfere a propriedade do item para essa organização. Deixará de ser o proprietário direto deste item depois de este ter sido movido.</value> <value>Escolha uma organização para a qual pretende mover este item. Mover para uma organização transfere a propriedade do item para essa organização. Deixará de ser o proprietário direto deste item depois de este ter sido movido.</value>
@@ -1451,7 +1451,7 @@ A leitura será efetuada automaticamente.</value>
<comment>Short for "Password Generator"</comment> <comment>Short for "Password Generator"</comment>
</data> </data>
<data name="NoFoldersToList" xml:space="preserve"> <data name="NoFoldersToList" xml:space="preserve">
<value>Não existem pastas para listar.</value> <value>Não pastas a enumerar.</value>
</data> </data>
<data name="FingerprintPhrase" xml:space="preserve"> <data name="FingerprintPhrase" xml:space="preserve">
<value>Frase de impressão digital</value> <value>Frase de impressão digital</value>
@@ -1556,7 +1556,7 @@ A leitura será efetuada automaticamente.</value>
<value>Sair</value> <value>Sair</value>
</data> </data>
<data name="ExitConfirmation" xml:space="preserve"> <data name="ExitConfirmation" xml:space="preserve">
<value>Tem a certeza de que deseja sair do Bitwarden?</value> <value>Tem a certeza de que pretende sair do Bitwarden?</value>
</data> </data>
<data name="PINRequireMasterPasswordRestart" xml:space="preserve"> <data name="PINRequireMasterPasswordRestart" xml:space="preserve">
<value>Pretende exigir o desbloqueio com a sua palavra-passe mestra quando a aplicação é reiniciada?</value> <value>Pretende exigir o desbloqueio com a sua palavra-passe mestra quando a aplicação é reiniciada?</value>
@@ -1570,7 +1570,7 @@ A leitura será efetuada automaticamente.</value>
<comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment> <comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment>
</data> </data>
<data name="SolarizedDark" xml:space="preserve"> <data name="SolarizedDark" xml:space="preserve">
<value>Solarized (escuro)</value> <value>Solarized Dark</value>
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment> <comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
</data> </data>
<data name="AutofillBlockedUris" xml:space="preserve"> <data name="AutofillBlockedUris" xml:space="preserve">
@@ -1583,7 +1583,7 @@ A leitura será efetuada automaticamente.</value>
<value>Pedir para adicionar um item se não o encontrar no seu cofre.</value> <value>Pedir para adicionar um item se não o encontrar no seu cofre.</value>
</data> </data>
<data name="OnRestart" xml:space="preserve"> <data name="OnRestart" xml:space="preserve">
<value>Quando reiniciar a aplicação</value> <value>Ao reiniciar a aplicação</value>
</data> </data>
<data name="AutofillServiceNotEnabled" xml:space="preserve"> <data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>O preenchimento automático facilita o acesso seguro ao seu cofre do Bitwarden a partir de outros sites e aplicações. Parece que o utilizador não configurou um serviço de preenchimento automático do Bitwarden. Configure o preenchimento automático do Bitwarden a partir do ecrã "Definições".</value> <value>O preenchimento automático facilita o acesso seguro ao seu cofre do Bitwarden a partir de outros sites e aplicações. Parece que o utilizador não configurou um serviço de preenchimento automático do Bitwarden. Configure o preenchimento automático do Bitwarden a partir do ecrã "Definições".</value>
@@ -1617,7 +1617,7 @@ A leitura será efetuada automaticamente.</value>
<value>Biometria</value> <value>Biometria</value>
</data> </data>
<data name="UseBiometricsToUnlock" xml:space="preserve"> <data name="UseBiometricsToUnlock" xml:space="preserve">
<value>Utilizar biometria para desbloquear</value> <value>Utilizar a biometria para desbloquear</value>
</data> </data>
<data name="AccessibilityOverlayPermissionAlert" xml:space="preserve"> <data name="AccessibilityOverlayPermissionAlert" xml:space="preserve">
<value>O Bitwarden precisa de atenção - Veja o "Serviço de acessibilidade de preenchimento automático" nas definições do Bitwarden</value> <value>O Bitwarden precisa de atenção - Veja o "Serviço de acessibilidade de preenchimento automático" nas definições do Bitwarden</value>
@@ -1689,7 +1689,7 @@ A leitura será efetuada automaticamente.</value>
<comment>Button text for an open operation (verb).</comment> <comment>Button text for an open operation (verb).</comment>
</data> </data>
<data name="UnableToSaveAttachment" xml:space="preserve"> <data name="UnableToSaveAttachment" xml:space="preserve">
<value>Houve um problema ao guardar este anexo. Se o problema persistir, poderá guardá-lo através do cofre web.</value> <value>Houve um problema ao guardar este anexo. Se o problema persistir, poderá guardá-lo através do cofre Web.</value>
</data> </data>
<data name="SaveAttachmentSuccess" xml:space="preserve"> <data name="SaveAttachmentSuccess" xml:space="preserve">
<value>Anexo guardado com sucesso</value> <value>Anexo guardado com sucesso</value>
@@ -1701,7 +1701,7 @@ A leitura será efetuada automaticamente.</value>
<value>Nenhum campo de palavra-passe detetado</value> <value>Nenhum campo de palavra-passe detetado</value>
</data> </data>
<data name="SoftDeleting" xml:space="preserve"> <data name="SoftDeleting" xml:space="preserve">
<value>A enviar para o lixo...</value> <value>A mover para o lixo...</value>
<comment>Message shown when interacting with the server</comment> <comment>Message shown when interacting with the server</comment>
</data> </data>
<data name="ItemSoftDeleted" xml:space="preserve"> <data name="ItemSoftDeleted" xml:space="preserve">
@@ -1729,7 +1729,7 @@ A leitura será efetuada automaticamente.</value>
<comment>(action prompt) Label for the search text field when viewing the trash folder</comment> <comment>(action prompt) Label for the search text field when viewing the trash folder</comment>
</data> </data>
<data name="DoYouReallyWantToPermanentlyDeleteCipher" xml:space="preserve"> <data name="DoYouReallyWantToPermanentlyDeleteCipher" xml:space="preserve">
<value>Pretende mesmo eliminar permanentemente? Isto não pode ser anulado.</value> <value>Pretende mesmo eliminar permanentemente? Esta ação não pode ser anulada.</value>
<comment>Confirmation alert message when permanently deleteing a cipher.</comment> <comment>Confirmation alert message when permanently deleteing a cipher.</comment>
</data> </data>
<data name="DoYouReallyWantToRestoreCipher" xml:space="preserve"> <data name="DoYouReallyWantToRestoreCipher" xml:space="preserve">
@@ -1737,7 +1737,7 @@ A leitura será efetuada automaticamente.</value>
<comment>Confirmation alert message when restoring a soft-deleted cipher.</comment> <comment>Confirmation alert message when restoring a soft-deleted cipher.</comment>
</data> </data>
<data name="DoYouReallyWantToSoftDeleteCipher" xml:space="preserve"> <data name="DoYouReallyWantToSoftDeleteCipher" xml:space="preserve">
<value>Pretende mesmo enviar para o lixo?</value> <value>Pretende mesmo mover para o lixo?</value>
<comment>Confirmation alert message when soft-deleting a cipher.</comment> <comment>Confirmation alert message when soft-deleting a cipher.</comment>
</data> </data>
<data name="AccountBiometricInvalidated" xml:space="preserve"> <data name="AccountBiometricInvalidated" xml:space="preserve">
@@ -1762,10 +1762,10 @@ A leitura será efetuada automaticamente.</value>
<value>Identificador da organização</value> <value>Identificador da organização</value>
</data> </data>
<data name="LoginSsoError" xml:space="preserve"> <data name="LoginSsoError" xml:space="preserve">
<value>Não foi possível iniciar sessão com SSO</value> <value>Atualmente não é possível iniciar sessão com SSO</value>
</data> </data>
<data name="SetMasterPassword" xml:space="preserve"> <data name="SetMasterPassword" xml:space="preserve">
<value>Definir palavra-passe mestra</value> <value>Definir a palavra-passe mestra</value>
</data> </data>
<data name="SetMasterPasswordSummary" xml:space="preserve"> <data name="SetMasterPasswordSummary" xml:space="preserve">
<value>Para concluir o início de sessão com SSO, por favor, defina uma palavra-passe mestra para aceder e proteger o seu cofre.</value> <value>Para concluir o início de sessão com SSO, por favor, defina uma palavra-passe mestra para aceder e proteger o seu cofre.</value>
@@ -1880,7 +1880,7 @@ A leitura será efetuada automaticamente.</value>
<value>Texto</value> <value>Texto</value>
</data> </data>
<data name="TypeTextInfo" xml:space="preserve"> <data name="TypeTextInfo" xml:space="preserve">
<value>O texto que deseja enviar.</value> <value>O texto que pretende enviar.</value>
</data> </data>
<data name="HideTextByDefault" xml:space="preserve"> <data name="HideTextByDefault" xml:space="preserve">
<value>Ao aceder ao Send, ocultar o texto por defeito</value> <value>Ao aceder ao Send, ocultar o texto por defeito</value>
@@ -1890,7 +1890,7 @@ A leitura será efetuada automaticamente.</value>
<value>Ficheiro</value> <value>Ficheiro</value>
</data> </data>
<data name="TypeFileInfo" xml:space="preserve"> <data name="TypeFileInfo" xml:space="preserve">
<value>O ficheiro que deseja enviar.</value> <value>O ficheiro que pretende enviar.</value>
</data> </data>
<data name="FileTypeIsSelected" xml:space="preserve"> <data name="FileTypeIsSelected" xml:space="preserve">
<value>O tipo de ficheiro está selecionado.</value> <value>O tipo de ficheiro está selecionado.</value>
@@ -1908,7 +1908,7 @@ A leitura será efetuada automaticamente.</value>
<value>Data de eliminação</value> <value>Data de eliminação</value>
</data> </data>
<data name="DeletionTime" xml:space="preserve"> <data name="DeletionTime" xml:space="preserve">
<value>Hora da eliminação</value> <value>Hora de eliminação</value>
</data> </data>
<data name="DeletionDateInfo" xml:space="preserve"> <data name="DeletionDateInfo" xml:space="preserve">
<value>O Send será permanentemente eliminado na data e hora especificadas.</value> <value>O Send será permanentemente eliminado na data e hora especificadas.</value>
@@ -1918,7 +1918,7 @@ A leitura será efetuada automaticamente.</value>
<value>Eliminação pendente</value> <value>Eliminação pendente</value>
</data> </data>
<data name="ExpirationDate" xml:space="preserve"> <data name="ExpirationDate" xml:space="preserve">
<value>Data de validade</value> <value>Prazo de validade</value>
</data> </data>
<data name="ExpirationTime" xml:space="preserve"> <data name="ExpirationTime" xml:space="preserve">
<value>Hora de validade</value> <value>Hora de validade</value>
@@ -1954,7 +1954,7 @@ A leitura será efetuada automaticamente.</value>
<value>Remover palavra-passe</value> <value>Remover palavra-passe</value>
</data> </data>
<data name="AreYouSureRemoveSendPassword" xml:space="preserve"> <data name="AreYouSureRemoveSendPassword" xml:space="preserve">
<value>Tem a certeza de que pretende remover a palavras-passe?</value> <value>Tem a certeza de que pretende remover a palavra-passe?</value>
</data> </data>
<data name="RemovingSendPassword" xml:space="preserve"> <data name="RemovingSendPassword" xml:space="preserve">
<value>A remover palavra-passe</value> <value>A remover palavra-passe</value>
@@ -2009,7 +2009,7 @@ A leitura será efetuada automaticamente.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="SendUpdated" xml:space="preserve"> <data name="SendUpdated" xml:space="preserve">
<value>Send atualizado</value> <value>Send guardado</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="NewSendCreated" xml:space="preserve"> <data name="NewSendCreated" xml:space="preserve">
@@ -2058,7 +2058,7 @@ A leitura será efetuada automaticamente.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="SendFileEmailVerificationRequired" xml:space="preserve"> <data name="SendFileEmailVerificationRequired" xml:space="preserve">
<value>Tem de verificar o seu e-mail para utilizar ficheiros com o Send. Pode verificar o seu e-mail no cofre web.</value> <value>Tem de verificar o seu e-mail para utilizar ficheiros com o Send. Pode verificar o seu e-mail no cofre Web.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="PasswordPrompt" xml:space="preserve"> <data name="PasswordPrompt" xml:space="preserve">
@@ -2080,7 +2080,7 @@ A leitura será efetuada automaticamente.</value>
<value>Palavra-passe mestra atualizada</value> <value>Palavra-passe mestra atualizada</value>
</data> </data>
<data name="UpdateMasterPassword" xml:space="preserve"> <data name="UpdateMasterPassword" xml:space="preserve">
<value>Atualizar palavra-passe mestra</value> <value>Atualizar a palavra-passe mestra</value>
</data> </data>
<data name="UpdateMasterPasswordWarning" xml:space="preserve"> <data name="UpdateMasterPasswordWarning" xml:space="preserve">
<value>A sua palavra-passe mestra foi recentemente alterada por um administrador da sua organização. Para aceder ao cofre, tem de atualizar a sua palavra-passe mestra agora. Ao prosseguir, terminará a sua sessão atual e terá de iniciar sessão novamente. As sessões ativas noutros dispositivos poderão continuar ativas até uma hora.</value> <value>A sua palavra-passe mestra foi recentemente alterada por um administrador da sua organização. Para aceder ao cofre, tem de atualizar a sua palavra-passe mestra agora. Ao prosseguir, terminará a sua sessão atual e terá de iniciar sessão novamente. As sessões ativas noutros dispositivos poderão continuar ativas até uma hora.</value>
@@ -2221,10 +2221,10 @@ A leitura será efetuada automaticamente.</value>
<value>Ajude o Bitwarden a melhorar a estabilidade da aplicação ao enviar relatórios de falhas.</value> <value>Ajude o Bitwarden a melhorar a estabilidade da aplicação ao enviar relatórios de falhas.</value>
</data> </data>
<data name="OptionsExpanded" xml:space="preserve"> <data name="OptionsExpanded" xml:space="preserve">
<value>As opções foram expandidas, clique para fechar.</value> <value>As opções estão expandidas, clique para as fechar.</value>
</data> </data>
<data name="OptionsCollapsed" xml:space="preserve"> <data name="OptionsCollapsed" xml:space="preserve">
<value>As opções foram fechadas, clique para expandir.</value> <value>As opções estão fechadas, clique para as expandir.</value>
</data> </data>
<data name="UppercaseAtoZ" xml:space="preserve"> <data name="UppercaseAtoZ" xml:space="preserve">
<value>Maiúsculas (A-Z)</value> <value>Maiúsculas (A-Z)</value>
@@ -2311,7 +2311,7 @@ A leitura será efetuada automaticamente.</value>
<value>Tem a certeza de que pretende ativar a captura de ecrã?</value> <value>Tem a certeza de que pretende ativar a captura de ecrã?</value>
</data> </data>
<data name="LogInRequested" xml:space="preserve"> <data name="LogInRequested" xml:space="preserve">
<value>Início de sessão pedido</value> <value>Pedido de início de sessão</value>
</data> </data>
<data name="AreYouTryingToLogIn" xml:space="preserve"> <data name="AreYouTryingToLogIn" xml:space="preserve">
<value>Está a tentar iniciar sessão?</value> <value>Está a tentar iniciar sessão?</value>
@@ -2326,7 +2326,7 @@ A leitura será efetuada automaticamente.</value>
<value>Endereço IP</value> <value>Endereço IP</value>
</data> </data>
<data name="Time" xml:space="preserve"> <data name="Time" xml:space="preserve">
<value>Tempo</value> <value>Hora</value>
</data> </data>
<data name="Near" xml:space="preserve"> <data name="Near" xml:space="preserve">
<value>Perto</value> <value>Perto</value>
@@ -2458,7 +2458,7 @@ A leitura será efetuada automaticamente.</value>
<value>Aleatório</value> <value>Aleatório</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve"> <data name="ConnectToWatch" xml:space="preserve">
<value>Ligar ao relógio</value> <value>Ligar ao Relógio</value>
</data> </data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Divulgação do serviço de acessibilidade</value> <value>Divulgação do serviço de acessibilidade</value>
@@ -2484,7 +2484,7 @@ Deseja mudar para esta conta?</value>
<value>É novo por cá?</value> <value>É novo por cá?</value>
</data> </data>
<data name="GetMasterPasswordwordHint" xml:space="preserve"> <data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Obter dica da palavra-passe mestra</value> <value>Obter a dica da palavra-passe mestra</value>
</data> </data>
<data name="LoggingInAsXOnY" xml:space="preserve"> <data name="LoggingInAsXOnY" xml:space="preserve">
<value>A iniciar sessão como {0} em {1}</value> <value>A iniciar sessão como {0} em {1}</value>
@@ -2758,10 +2758,10 @@ Deseja mudar para esta conta?</value>
<value>Segurança da conta</value> <value>Segurança da conta</value>
</data> </data>
<data name="BitwardenHelpCenter" xml:space="preserve"> <data name="BitwardenHelpCenter" xml:space="preserve">
<value>Centro de ajuda Bitwarden</value> <value>Centro de ajuda do Bitwarden</value>
</data> </data>
<data name="ContactBitwardenSupport" xml:space="preserve"> <data name="ContactBitwardenSupport" xml:space="preserve">
<value>Contactar o suporte Bitwarden</value> <value>Contactar o suporte do Bitwarden</value>
</data> </data>
<data name="CopyAppInformation" xml:space="preserve"> <data name="CopyAppInformation" xml:space="preserve">
<value>Copiar informações da aplicação</value> <value>Copiar informações da aplicação</value>
@@ -2807,7 +2807,7 @@ Deseja mudar para esta conta?</value>
<value>Opções adicionais</value> <value>Opções adicionais</value>
</data> </data>
<data name="ContinueToWebApp" xml:space="preserve"> <data name="ContinueToWebApp" xml:space="preserve">
<value>Continuar para a aplicação web?</value> <value>Continuar para a aplicação Web?</value>
</data> </data>
<data name="ContinueToX" xml:space="preserve"> <data name="ContinueToX" xml:space="preserve">
<value>Continuar para {0}?</value> <value>Continuar para {0}?</value>
@@ -2826,10 +2826,10 @@ Deseja mudar para esta conta?</value>
<value>Continuar para a loja de aplicações?</value> <value>Continuar para a loja de aplicações?</value>
</data> </data>
<data name="TwoStepLoginDescriptionLong" xml:space="preserve"> <data name="TwoStepLoginDescriptionLong" xml:space="preserve">
<value>Torne a sua conta mais segura configurando o login em duas etapas na aplicação web Bitwarden.</value> <value>Torne a sua conta mais segura configurando a verificação de dois passos na aplicação Web Bitwarden.</value>
</data> </data>
<data name="ChangeMasterPasswordDescriptionLong" xml:space="preserve"> <data name="ChangeMasterPasswordDescriptionLong" xml:space="preserve">
<value>Pode alterar a sua palavra-passe mestra na aplicação web Bitwarden.</value> <value>Pode alterar a sua palavra-passe mestra na aplicação Web Bitwarden.</value>
</data> </data>
<data name="YouCanImportDataToYourVaultOnX" xml:space="preserve"> <data name="YouCanImportDataToYourVaultOnX" xml:space="preserve">
<value>Pode importar dados para o seu cofre em {0}.</value> <value>Pode importar dados para o seu cofre em {0}.</value>
@@ -2845,13 +2845,13 @@ Deseja mudar para esta conta?</value>
<value>Consulte a nossa política de privacidade em bitwarden.com.</value> <value>Consulte a nossa política de privacidade em bitwarden.com.</value>
</data> </data>
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve"> <data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
<value>Explore mais funcionalidades da sua conta Bitwarden na aplicação web.</value> <value>Explore mais funcionalidades da sua conta Bitwarden na aplicação Web.</value>
</data> </data>
<data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve"> <data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve">
<value>O Bitwarden permite-lhe partilhar os seus itens do cofre com outras pessoas através da utilização de uma organização. Saiba mais no site bitwarden.com.</value> <value>O Bitwarden permite-lhe partilhar os seus itens do cofre com outras pessoas através da utilização de uma organização. Saiba mais no site bitwarden.com.</value>
</data> </data>
<data name="RateAppDescriptionLong" xml:space="preserve"> <data name="RateAppDescriptionLong" xml:space="preserve">
<value>Ajude outras pessoas a descobrir se o Bitwarden é adequado para elas. Visite a loja de aplicações e deixe uma avaliação agora.</value> <value>Ajude outras pessoas a descobrir se o Bitwarden lhes é adequado. Visite a loja de aplicações e deixe uma avaliação agora.</value>
</data> </data>
<data name="DefaultDarkThemeDescriptionLong" xml:space="preserve"> <data name="DefaultDarkThemeDescriptionLong" xml:space="preserve">
<value>Escolha o tema escuro a utilizar quando o modo escuro do seu dispositivo estiver a ser utilizado</value> <value>Escolha o tema escuro a utilizar quando o modo escuro do seu dispositivo estiver a ser utilizado</value>
@@ -2875,4 +2875,13 @@ Deseja mudar para esta conta?</value>
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve"> <data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
<value>Configure uma opção de desbloqueio para alterar a ação de tempo limite do seu cofre.</value> <value>Configure uma opção de desbloqueio para alterar a ação de tempo limite do seu cofre.</value>
</data> </data>
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
<value>A verificação de dois passos Duo é necessária para a sua conta. </value>
</data>
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
<value>Siga os passos do Duo para concluir o início de sessão.</value>
</data>
<data name="LaunchDuo" xml:space="preserve">
<value>Iniciar o Duo</value>
</data>
</root> </root>

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