1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-17 08:43:21 +00:00

Compare commits

..

84 Commits

Author SHA1 Message Date
Rico Acosta
8a1bc79eba Update config.yml
CS wants to bring more attention to the autofill report, requests changing to UPPCASE
2023-01-24 15:57:46 -06:00
aj-rosado
dbfd15b819 [PS-2275] Update the default kdf iterations to 600k. (#2305)
* [PS-2275] Update the default kdf iterations to 350k.

* update to 600k per latest owasp
2023-01-24 20:08:52 +00:00
Daniel James Smith
acd0cb119d [PS-2324] Add honorific title mx (#2313) 2023-01-23 16:28:04 +01:00
André Bispo
d61bc4b5c1 [SG-460] Master Password security checks (mobile) (#2312)
* [SG-886] MasterPassword Strength Indicator (#2238)

* [SG-886] Add password strength indicator control

* [SG-570] Add weak password dialog check

* [SG-886] rename enum password strength

* [SG-886] Change control scale

* [SG-886] Move calculate user inputs to IPasswordGenerationService, refactor.

* [SG-886] Move formatted string to xaml. Move minimum chars to constant

* [SG-886] String to enum converter

* [SG-886] PR fixes. Code refactor control

* [SG-886] Update UI on OS theme change.

* [SG-886] Move colors to view

* [SG-886] Fixed password strength validation

* [SG-564][SG-565] Check Exposed Password (#2239)

* [SG-886] Add password strength indicator control

* [SG-570] Add weak password dialog check

* [SG-886] rename enum password strength

* [SG-564] [SG-565] Add check for exposed password and show dialog

* code format

* [SG-886] Change control scale

* [SG-886] Move calculate user inputs to IPasswordGenerationService, refactor.

* [SG-886] Move formatted string to xaml. Move minimum chars to constant

* [SG-886] String to enum converter

* [SG-886] Remove import

* [SG-886] Update UI on OS theme change.

* [SG-886] Move colors to view

* [SG-886] Fixed password strength validation
2023-01-20 13:38:31 +00:00
github-actions[bot]
5aa1146657 Autosync the updated translations (#2310)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-01-20 12:54:47 +01:00
André Bispo
f15fd246a8 Passwordless login 2FA not working (#2289)
* [SG-174] Fix 2FA passwordless login

* [SG-982] Enable login with device
2023-01-16 18:25:44 +00:00
Michał Chęciński
2b8547878a Fix autobump workflow (#2298) 2023-01-16 18:45:23 +01:00
github-actions[bot]
942d5d29d2 Bumped version to 2023.1.1 (#2297)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-01-16 10:29:15 +01:00
github-actions[bot]
fde63a836d Autosync the updated translations (#2292)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-01-13 10:03:24 +01:00
Brandon Maharaj
6102a0c115 [SG-912] Modify the mobile app to retrieve the user's avatar color (#2284)
* [SG-912] Modify the mobile app to retrieve the user's avatar color (#2277)

* work: baseline

* fix: dont use profile for store

* fiix: use userid in key

* fix: lookup on AccountView list create

* fix my own bad advice + tweaks

* Autosync the updated translations (#2279)

* fix my own bad advice + tweaks

* fiix: use userid in key

* [PS-1352] Fix ignore diacritics in search (#2044)

* Fix ignore diacritics in search

This change updates the search function to ignore diacritical marks in search results. Marks are stripped from both the search input and results.

* Removed logs, added null or whitespace validation and improved formatting


* [PS-2145] add rainsee browser series support (#2272)

* fix: lookup on AccountView list create

* Autosync the updated translations (#2279)

* fix my own bad advice + tweaks

* fix: single state grab is cool
2023-01-12 13:27:10 -05:00
Federico Maccaroni
4f4953206e [EC-469] Improve ApiException message (#2288)
* EC-469 Improve ApiException message to have the validation errors and message provided by the ErrorResponse

* EC-469 Updated default message format for ErrorResponse GetFullMessage()
2023-01-12 10:31:27 -03:00
github-actions[bot]
f772ee7068 Bumped version to 2023.1.0 (#2287)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-01-11 09:55:57 +01:00
Matt Bishop
8f93e6bf5f Upload and process test results as an artifact and report (#2286) 2023-01-10 13:48:22 -05:00
André Bispo
64fefac194 [SG-978] Added queries to http and https into manifest (#2282) 2023-01-06 13:46:03 -05:00
github-actions[bot]
d784b1290b Autosync the updated translations (#2279)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2023-01-06 01:23:41 +01:00
Auj625197595
0f2bc2fa25 [PS-2145] add rainsee browser series support (#2272) 2023-01-05 17:23:09 +00:00
noncenz
0e856d2add [PS-1352] Fix ignore diacritics in search (#2044)
* Fix ignore diacritics in search

This change updates the search function to ignore diacritical marks in search results. Marks are stripped from both the search input and results.

* Removed logs, added null or whitespace validation and improved formatting

Co-authored-by: aj-rosado <109146700+aj-rosado@users.noreply.github.com>
Co-authored-by: Andre Rosado <arosado@bitwarden.com>
2023-01-05 16:34:06 +00:00
mp-bw
acc587ce45 Fix repo url for F-Droid 1.15+ (#2276) 2023-01-04 14:28:47 -03:00
Daniel James Smith
66180397d9 Add needs-qa label to BANNED_LABELS (#2274) 2023-01-03 20:09:13 +01:00
Federico Maccaroni
571c4b8d22 EC-819 Update iOS app icon (#2270) 2022-12-30 17:52:25 +00:00
Federico Maccaroni
660ba3d722 [EC-628] Added Crashlytics to the watchOS project (#2267)
* EC-628 Added Crashlytics to the watchOS project, missing GoogleService-Info.plist for now

* addition of GoogleServices-info.plist.gpg

* Re-add GoogleService-info.plist.gpg

* EC-628 Updated build.yml to decrypt and copy the GoogleService-Info.plist for Crashlytics and also added step to upload Watch dSYMs to Crashlytics

* EC-628 Fix run command upload watch dsym build.yml

* EC-628 Updated Apple iOS macos version to 12 in order to resolve Watch XCode dependencies correctly with SPM

* EC-628 Added some logs to see where I'm located cause it's issuing a wrong path. Also deactivated droid builds so that it's faster to test and doesn't consume resources on that till the build is OK

* EC-628 fixed variable reference build.yml

* EC-628 Removed ls of watch dsym export path before creating the folder that was causing the build to fail

* EC-628 Removed XCode build phase step to auto-upload dsym to firebase and added some logs to find the upload-symbols tool from SPM. Also fix making the dir for the watchOS dSYMs export path

* EC-628 Changed approach to upload watch dSYMs to Firebase by finding the upload-symbols script dynamically with find and then executing it

* EC-628 Added missing ; to command to upload watch dSYMs

* EC-628 Fix buld.yml Watch dSYMs copy to export path

* EC-628 Cleaned build.yml for the watch dSYMs upload to Firebase and bring back droid builds

Co-authored-by: sneakernuts <671942+sneakernuts@users.noreply.github.com>
2022-12-30 17:51:35 +00:00
Kevinlinpr
414cb9bd7e [PS-2116] feat(Support): Add Lemur Browser (#2262)
*  feat(Support): Add Lemur Browser

Lemur Browser is the mobile browser support Chrome and Edge extensions, build from chromium.

🔗 issue - https://github.com/bitwarden/mobile/issues/2260
🔗 Lemur Browser - https://www.lemurbrowser.com/

* 🐞 fix(Sorted alphabetically): Move up one line

Please move this up one line to ensure the sections are sorted alphabetically

6d5cb73445
2022-12-30 13:38:05 +01:00
github-actions[bot]
e588efd0a1 Autosync the updated translations (#2271)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2022-12-30 01:19:00 +01:00
Federico Maccaroni
1cdba5f73d EC-868 clear console logging (#2265) 2022-12-29 15:00:13 -03:00
Dan Alcantara
cbccd10271 Add support for the Neeva app (#2045) 2022-12-28 13:19:16 +01:00
Şahin BEZENG
6de6b19944 Add support for Dezor Browser (#2142) 2022-12-28 13:08:40 +01:00
Daniel James Smith
5493b00957 Fix link to contributing docs (#2266) 2022-12-26 17:38:55 +01:00
Federico Maccaroni
81988a7fe7 EC-820 Added icons for Watch Complication and updated the Watch app icons (#2258) 2022-12-23 22:39:50 +00:00
André Bispo
b91ff09e27 [SG-174] Remove login with device button (#2259) 2022-12-23 17:11:14 +00:00
github-actions[bot]
945627d649 Autosync the updated translations (#2257)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2022-12-23 01:53:00 +01:00
Federico Maccaroni
307c71ee07 EC-847 improved watch list ui performance by removing the animations on the search box and going back to the simple List instead of the TrackableWithHeaderListView (#2256) 2022-12-22 19:06:21 +00:00
Federico Maccaroni
e72932cbaa [EC-835] Add kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly on Watch Keychain (#2250)
* EC-835 Added in the Watch app keychain accessible when passcode set this device only and when the passcode is set to signal the iPhone to trigger a sync on opening the watch app

* EC-835 Embed LocalAuthentication framework into the watch app to fix no such module when importing it

* EC-835 Changed approach to check if Watch has passcode enabled by using Keychain accessible kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly instead of LAContext

* EC-835 Fix weird error saying unassigned local variable on the CI compiler. It seems it doesn't realize of the full condition
2022-12-22 17:59:12 +00:00
mp-bw
4347c2f81d Android: Show auto-totp-copy toast on pre-13 devices (#2249) 2022-12-19 14:03:22 -03:00
github-actions[bot]
619acfe0fe Autosync the updated translations (#2247)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2022-12-16 18:30:52 +01:00
André Bispo
05765c2af9 Remove unused resource entry SelectAddTotpToStoreTheKeySafely (#2248) 2022-12-16 16:26:59 +01:00
Federico Maccaroni
728182de6c [EC-844] Improve Apple Watch states (#2246)
* EC-844 improve need login / need setup states on the watch

* EC-844 Fix naming of things and moved constant to the proper place to maintain format. Also removed UpdateLastUserShouldConnectToWatchAsync from the interface of the StateService given that it's not used outside the service and made it private
2022-12-15 15:21:29 -03:00
Federico Maccaroni
a19b5c4e05 EC-842 Delete items that are not included in the sync to the watch (#2242) 2022-12-15 13:03:34 -03:00
Federico Maccaroni
f6895a0733 EC-846 Revert build.yml Android was not being built because a condition added while developing the Apple Watch app in another branch merged to master (#2245) 2022-12-15 10:57:10 -03:00
Federico Maccaroni
3e48b7a968 EC-785 Bumped Apple Watch version to 2022.12.0 (#2243) 2022-12-14 22:03:06 +00:00
Todd Martin
ebf65ecb96 Set push token state values to be user-specific (#2200)
* Changed the current push token and last registration time to be user-based

* Fixed compile error.

* Fixed interface implementation.

* Fixed compile error for Android.

* Refactored to handle getting active user ID within state service

* Refactored methods allow existing logic to handle getting the active user.

* Updated to reconcile options.

* Updated naming and fixed issue with UserId.

* Removed space between constants.
2022-12-14 16:07:04 -05:00
github-actions[bot]
37dab0928b Bumped version to 2022.12.0 (#2241)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2022-12-14 21:04:08 +00:00
André Bispo
aa0544cd3d [SG-872] Create generic exception handler for mobile (#2222)
* [SG-872] Add method to handle exception in BaseViewModel

* [SG-872] Code format
2022-12-13 21:53:04 +00:00
André Bispo
f4b4cfc9de [SG-870] Add null check on notification received (#2221) 2022-12-13 21:50:05 +00:00
Federico Maccaroni
7785b2dbf9 EC-841 Fix Watch fetch cipher and added condition for previews (#2236) 2022-12-13 19:36:45 +00:00
Federico Maccaroni
e3dafb502b EC-834 Watch UI/UX fixes (#2234) 2022-12-13 14:50:55 -03:00
Federico Maccaroni
b30fc12135 EC-830 Fix state checking when watch app had already been installed before, so reset it if first run. (#2232) 2022-12-13 11:27:33 -03:00
Federico Maccaroni
28d204f2b1 EC-833 fix WatchDeviceService registration to be called from the extensions appropiately (#2233) 2022-12-13 11:27:15 -03:00
github-actions[bot]
1a3ff5ec41 Autosync the updated translations (#2230)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2022-12-09 11:59:54 +01:00
flawedworld
2f6fd476a2 Add support for Vanadium in GrapheneOS (#2199)
Co-authored-by: mp-bw <59324545+mp-bw@users.noreply.github.com>
2022-12-08 10:07:06 -05:00
mp-bw
7a08452fa8 Automatically continue when enter key pressed during email entry (#2227) 2022-12-07 16:51:32 +00:00
Álison Fernandes
fa6bac3b43 EC-395 Apple Watch MVP (#2228)
* [EC-426] Add watchOS PoC app (#2054)

* EC-426 Added watchOS app, configured iOS.csproj to bundle the output of XCode build into the Xamarin iOS app and added some custom logic to use WCSession to communicate between the iOS and the watchOS apps

* EC-426 Removed Info.plist from iOS.Core project given that it's not needed

* [EC-426] Added new encrypted watch app profiles

* EC-426 added configuration for building watchApp and bundle it up on the iOS one

* EC-426 Fix build for watchOS

* EC-426 Fix build for watchOS applied shell bash

* EC-426 Fix build for watchOS echo

* EC-426 Fix build for watchOS simplify

* EC-426 Fix build for watchOS added workspace path

* EC-426 Changed code sign identity of watchOS project to Apple Distribution

* EC-426 added manual code sign style and specified the provisioning profile for the targets on the watch xcode project

* EC-426 updated path to watchOS on release on iOS.csproj and disabled android and f-.droid

* EC-426 fix build

* EC-426 fix path and check listing of directory of watchOS output just in case

* EC-426 Fix Apple Watch build to list the folder recursively just in case we need to change the path for the watch bundle

* EC-426 TEMP Change texts on input on login and lock to show that the app is for the Watch PoC testing

* EC-426 Fix WatchApp build path

* EC-426 Added WatchOS AppIcons

* EC-426 added gitignore for XCode project removed files supposed to be ignored

* EC-426 Cleaned the code a bit to avoid misbehavior

* EC-426 Code cleanup

Co-authored-by: Joseph Flinn <joseph.s.flinn@gmail.com>

* [EC-585] Added data, encryption and some helpers and structure to the Watch app (#2164)

* [EC-585] Added foundation classes on the watch to handle CoreData and some fixes on the communication of the ciphers, also some helper classes to store in keychain and encrypt data

* EC-585 Added keychain helper, encryption helpers and added data storage using CoreData configuring it appropiately. View and ViewModel are here only to test that the fetching/saving works but it's not the actual UI of the watch app. Also removed all the places where the automatic file signature was added by XCode

* EC-585 Fixed CipherServiceMock to implement protocol

* EC-585 Fixed DeviceActionService duplicated services

* [EC-614] Apple Watch MVP Cipher list UI (#2175)

* [EC-585] Added foundation classes on the watch to handle CoreData and some fixes on the communication of the ciphers, also some helper classes to store in keychain and encrypt data

* EC-585 Added keychain helper, encryption helpers and added data storage using CoreData configuring it appropiately. View and ViewModel are here only to test that the fetching/saving works but it's not the actual UI of the watch app. Also removed all the places where the automatic file signature was added by XCode

* EC-585 Fixed CipherServiceMock to implement protocol

* EC-585 Fixed DeviceActionService duplicated services

* EC-614 Implemented watch ciphers list UI

* [EC-615] Apple Watch MVP Cipher details UI (#2192)

* [EC-585] Added foundation classes on the watch to handle CoreData and some fixes on the communication of the ciphers, also some helper classes to store in keychain and encrypt data

* EC-585 Added keychain helper, encryption helpers and added data storage using CoreData configuring it appropiately. View and ViewModel are here only to test that the fetching/saving works but it's not the actual UI of the watch app. Also removed all the places where the automatic file signature was added by XCode

* EC-585 Fixed CipherServiceMock to implement protocol

* EC-585 Fixed DeviceActionService duplicated services

* EC-614 Implemented watch ciphers list UI

* EC-615 Added cipher details UI to watch and also implemented logic and helpers to generate the TOTPs

* EC-615 Added value transformer to login uris on the cipher entity

* EC-617 Added state view on watch app and some state helpers and wired it on the CipherListView. Also added some images (#2195)

* [EC-581] Implement Apple Watch MVP Sync (#2206)

* EC-581 Implemented sync iPhone -> watchOS, fix some issues with the watch database and sync flows for login/locks/multiple accounts

* EC-581 Added watch sync on unlocking and need setup state when no user is synced and the session is not active

* EC-581 Removed unused method

* EC-581 Fix format

* EC-759 Added avatar row on cipher list header to display avatar icon and email (#2213)

* [EC-786] Apple Watch MVP Sync fixes (#2214)

* EC-786 Commented things that are not going to be included on the MVP and fixed issue on the dictionary sent on the applicationContext to have a changing key based on time

* EC-786 Commented need unlock state

* EC-579 Added logic for Connect To Watch on iOS settings and moved it to the correct place. Also improved the synchronization and watch session activation logic (#2218)

* EC-616 Added search header for ciphers and polished the code (#2226)

Co-authored-by: Federico Maccaroni <fedemkr@gmail.com>
Co-authored-by: Joseph Flinn <joseph.s.flinn@gmail.com>
2022-12-07 11:39:20 -05:00
André Bispo
2a60ff62d8 [SG-601] Enhance experience when user denies camera access in Authenticator (#2205)
* [SG-601] Handle camera denied permissions

* [SG-601] Code format

* [SG-601] PR Fixes

* [SG-601] Change resource text to singular

* [SG-601] Remove horizontal and vertical options

* [SG-601] Add start and stop scanner methods

* [SG-601] Remove parameter from ScanPage

* [SG-601] Move initialization to viewmodel

* [SG-601] Fix zxing scanning bug

* [SG-601] Move RunUIThread inside of method
2022-12-06 16:30:46 +00:00
github-actions[bot]
eaa4f193ce Bumped version to 2022.11.1 (#2224)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2022-12-05 13:56:00 -08:00
mp-bw
6973a0b71c [BEEEP] Support for automatic TOTP token copy via external autofill (Android) (#2220)
* Android: Support for automatic TOTP copy via external autofill

* update iOS autofill interface

* additional tweaks
2022-12-05 12:49:34 -05:00
Opeyemi
bafd9ff85d update ::set-output to the latest method (#2217)
* update ::set-output to the latest method

* Update workflow for linter error
2022-12-05 15:04:34 +00:00
aj-rosado
4580033477 [PS-1707] improve dark layout colors (#2209)
* [PS-1707] Changed the callout color to a Theme Color

* [PS-1707] Changed color defaults to defined colors

* [PS-1707] Added an effect to change the switch hint color to a theme color

* [PS-1707] Removed HintColorSwitchEffect and added the content to the CustomSwitchRenderer to affect all switches and update on theme change
2022-12-02 16:38:25 +00:00
github-actions[bot]
a4673021a9 Autosync the updated translations (#2215)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2022-12-02 01:28:13 +01:00
github-actions[bot]
8e2e143e6f Bumped version to 2022.11.0 (#2212)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2022-12-01 16:56:36 +00:00
André Bispo
f43f9171e5 [SG-860] Add condition to execute notification tap code (#2211) 2022-12-01 11:58:27 +00:00
github-actions[bot]
3c8a8862ca Autosync the updated translations (#2204)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2022-11-25 01:26:09 +01:00
Álison Fernandes
969b89bb4d SG-837 Fixes: QA build crashing while attaching (#2203) 2022-11-24 15:49:12 +00:00
github-actions[bot]
164b8970d3 Autosync the updated translations (#2198)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2022-11-18 04:39:37 +01:00
André Bispo
34fd30e157 [SG-831] Pull Down Sync does not retrieve pending AuthRequests (#2196)
* [SG-831] Pull to refresh forces refresh.

* [SG-831] Expose sync login request method to be used independently

* [SG-831] Change sync order
2022-11-17 16:02:34 +00:00
André Bispo
8e09f0cc15 [SG-808] Change navigation on remove account after logout by timeout (#2193) 2022-11-16 12:38:45 +00:00
André Bispo
693a4ef776 [SG-816] Get all login requests and pick the most recent (#2191)
* [SG-816] Get all login requests anfd pick the most recent

* [SG-816] Add check if active user has approve login with device active

* [SG-816] Build fix. Fix response model.

* [SG-816] Move code to sync service
2022-11-15 17:36:21 +00:00
André Bispo
0992a989d4 [SG-778] Adjust mobile client to handle previously-responded-to passwordless request (#2190)
* [SG-778] Add properties to response model

* [SG-778] Add validation for request already answered

* [SG-778] Remove unnecessary properties

* [SG-778] Remove unnecessary assignments
2022-11-15 14:17:26 +00:00
Todd Martin
1b137a8a8a Added check to make sure it doesn't set a deployment on a Dry Run. (#2188) 2022-11-14 13:43:45 -05:00
André Bispo
7e8e86a77a [SG-813] Not You? crashes app after vault logout timeout (#2184)
* Merge branch 'master' into feature/SG-174-login-with-device

* [SG-813] Fix merge

* [SG-813] rename HomePage parameter name

* [SG-813] Added NavParams for home page on account switching.

* [SG-813] Remove account showing when adding new account.

* [SG-813] Add account switch pop up if email already exists

* [SG-813] Add default account avatar to HomePage

* [SG-813] Code format

* [SG-813] Remove unused import

* [SG-813] Renamed checkNavigateLogin to shouldCheckRememberEmail

* [SG-813] Move prompt account switch to account manager service

* [SG-813] Remove Account button appears if email is the same as the ActiveUser

* [SG-813] Fix code duplicate

* [SG-813] Fix for android RemoveAccount button

* [SG-813] Code format
2022-11-11 18:14:30 +00:00
Robyn MacCallum
20c1e2d7f2 Add syncCompleted to check to get passwordless requests (#2186) 2022-11-11 12:33:17 -05:00
github-actions[bot]
7870c2706b Autosync the updated translations (#2185)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2022-11-11 12:34:15 +01:00
Patrick
5a5f50605b Update AppResources.resx (#2181) 2022-11-10 13:44:18 -05:00
Robyn MacCallum
0106732cbd [SG-808] Only show 'remove account' option if user is in Accounts list (#2179)
* Only show 'remove account' option if user is in Accounts list

* Condense existing email logic

* Add line break

* Condense to local variable

* Cleanup spacing
2022-11-10 07:06:17 -05:00
André Bispo
9ae269dd57 [SG-174] Login with Device Request - Mobile (#2167)
* [SG-174] Add new login request services to Api

* [SG-174] Fix typo

* [SG-174] Enable login with device button.

* [SG-174] Add new login request page and viewmodel

* [SG-174] Add new text resources

* [SG-174] Add new RSA Decrypt method with string param

* [SG-174] Change create login request method

* [SG-174] Add new method to auth service to login passwordless

* [SG-174] Refactor login helper method to work with passwordless

* [SG-174] Fix service registration

* [SG-174] Update token request to support passwordless

* [SG-174] Update Api service with passwordless methods

* [SG-174] Fix App csproj references

* [SG-174] Remove unnecessary argument

* [SG-174] dotnet format

* [SG-174] Fixed iOS Extensions

* [SG-174] Change Command to ICommand

* [SG-174] Change Gesture Recognizer to Command

* [SG-174] Fix close action

* [SG-174] Code format

* [SG-174] Fix android frame shadow bug

* [SG-174] PR fixes
2022-11-09 16:25:48 +00:00
Opeyemi
04ed47d545 Devops 1039 update release flow dry run step names (#2177) 2022-11-08 22:44:50 +00:00
Opeyemi
6160535c03 add run-name for release to include workflow trigger (#2174) 2022-11-08 20:27:22 +00:00
André Bispo
8d92373c88 [SG-806] add try catch on initAsync (#2173) 2022-11-07 13:41:02 +00:00
André Bispo
6bfc8f7d49 [SG-802] Add if check on notification tap. (#2172) 2022-11-07 13:40:48 +00:00
André Bispo
69f02eef82 [SG-800] Selecting notification for inactive account on iOS while app is open does not display the request (#2166)
* [SG-800] Remove await from ActionSheet
If the user never answers the pop up, the lock is never released.

* [SG-800] Add try catch
2022-11-04 16:54:16 +00:00
github-actions[bot]
02b8e54988 Autosync the updated translations (#2165)
Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com>
2022-11-04 08:11:43 +01:00
Álison Fernandes
99472d2548 [EC-655] Adds build variants to the mobile codebase using a CAKE script (#2161)
* Implemented CAKE build script

* cake script now deals with all of iOS's .plists

* cake now updates iOS bundleid's / Android packagename in codefiles

* iOS Bundle ID / Name should be correctly handled now + refactor

* tabs -> spaces

* Additional code files are now handled by cake

* Additional iOS codefile changes required

* Android's Autofill Label is now changed

* Removed dash from packagenames / bundleIDs

* Fixed CFBundleURLName set

* Added google-services.json to cake preprocessing

* Add CAKE to build workflow
- Android

* Add debug

* Updated cake's GitVersion.Tool

* AndroidManifest manual parsing needs to happen first

* Added Android Constants to build.cake

* [SG-747] Add Android QA build to mobile build pipeline (#2144)

* Add checkout depth

* Build and upload QA artifacts

* Remove missing .aab

* Update build.yml

* Update paths

* Update var names

* Build and upload QA artifacts

* Add in matrix to path.

* Lets not fail all the jobs if something pukes

* Add in some flow logic for QA

* We need strings in pwsh

* Remove extra quotes

* Testing, remove uneeded runs

* Test folder items

* [SG-747] Added more debug info to find problem

* [SG-747] copy signed apk to correct file name for each app variant

* [SG-747] try to fix if statement

* [SG-747] separate decrypt google services into another step with condition.

* [SG-747] fixed typo and line break

* [SG-747] added debug to check output path

* [SG-747] fix package name

* [SG-747] Fixed condition of step execution

* [SG-747] test if cases

* [SG-747] Code clean up

* [SG-747] Added FDroid and iOS steps.

* [SG-747] Removed test step

* [SG-747] Step name changes

* Update condition to be more inclusive

Co-authored-by: Álison Fernandes <vvolkgang@users.noreply.github.com>

* [SG-747] Expand if condition to allow more build types other than QA

* [SG-747] removed execution condition

Co-authored-by: mimartin12 <77340197+mimartin12@users.noreply.github.com>

* Apply suggestions from code review

Linter suggestions

Co-authored-by: mimartin12 <77340197+mimartin12@users.noreply.github.com>
Co-authored-by: Micaiah Martin <mmartin@bitwarden.com>
Co-authored-by: mimartin12 <77340197+mimartin12@users.noreply.github.com>
Co-authored-by: Álison Fernandes <vvolkgang@users.noreply.github.com>
Co-authored-by: Todd Martin <106564991+trmartin4@users.noreply.github.com>

* Base bundle ID refactor and cleaned up TODOs

- Added base vars for the bundle IDs
- Removed a TODO and explained the remaining ones
- Commented a unused var, keeping it in the code as this might be useful later

Co-authored-by: Micaiah Martin <mmartin@bitwarden.com>
Co-authored-by: Federico Andrés Maccaroni <fedemkr@gmail.com>
Co-authored-by: Todd Martin <tmartin@bitwarden.com>
Co-authored-by: André Bispo <abispo@bitwarden.com>
Co-authored-by: mimartin12 <77340197+mimartin12@users.noreply.github.com>
Co-authored-by: Todd Martin <106564991+trmartin4@users.noreply.github.com>
2022-11-01 22:14:49 +00:00
Carlos Gonçalves
5a4c81bd75 SG-769 - Ensured token for decoding is refreshed before use (#2150) 2022-10-31 15:46:10 -04:00
Carlos Gonçalves
ee09c0abda SG-786 - Fix 400 error code log outs without invalid_grant (#2156)
* SG-786 - Added validation to check if the 400 error is invalid grant

* SG 786 - Improved code quality
2022-10-31 13:40:26 -04:00
André Bispo
9baa79e10b [SG-773][SG-775] Duplicate passwordless login requests (#2160)
* [SG-773] Change method call to message send

* [SG-773] Introduce lock to avoid concurrent executions of login requests

* [SG-773][SG-775] add comment

* [SSG-773][SG-775] Refactor passwordlessLoginRequest string to constant
2022-10-31 15:57:09 +00:00
André Bispo
a8909a3ce6 [SG-765] Add cancel button to passwordless login modal on android (#2159) 2022-10-31 15:06:37 +00:00
359 changed files with 17620 additions and 2008 deletions

View File

@@ -1,6 +1,6 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: Report mobile autofill failure - name: Report mobile AUTOFILL failure
url: https://docs.google.com/forms/d/e/1FAIpQLScMopHyN7KGJs8hW562VTzbIGL4KcFnx0wJcsW0GYE1BnPiGA/viewform url: https://docs.google.com/forms/d/e/1FAIpQLScMopHyN7KGJs8hW562VTzbIGL4KcFnx0wJcsW0GYE1BnPiGA/viewform
about: We are aware of some situations where the Bitwarden mobile app will not autofill information correctly. This is something the Bitwarden team is actively working on but need your help as a community and active Bitwarden users! about: We are aware of some situations where the Bitwarden mobile app will not autofill information correctly. This is something the Bitwarden team is actively working on but need your help as a community and active Bitwarden users!
- name: Feature Requests - name: Feature Requests

View File

@@ -14,6 +14,10 @@
<string>Dist: Extension 2021</string> <string>Dist: Extension 2021</string>
<key>com.8bit.bitwarden.share-extension</key> <key>com.8bit.bitwarden.share-extension</key>
<string>Dist: Share Extension 2021</string> <string>Dist: Share Extension 2021</string>
<key>com.8bit.bitwarden.watchkitapp</key>
<string>Dist: Bitwarden Watch App</string>
<key>com.8bit.bitwarden.watchkitapp.watchkitextension</key>
<string>Dist: Bitwarden Watch App Extension</string>
</dict> </dict>
</dict> </dict>
</plist> </plist>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -4,10 +4,10 @@ name: Build
on: on:
push: push:
branches-ignore: branches-ignore:
- 'l10n_master' - "l10n_master"
- 'gh-pages' - "gh-pages"
paths-ignore: paths-ignore:
- '.github/workflows/**' - ".github/workflows/**"
workflow_dispatch: workflow_dispatch:
inputs: {} inputs: {}
@@ -42,15 +42,15 @@ jobs:
id: branch-check id: branch-check
run: | run: |
if [[ $(git ls-remote --heads origin rc) ]]; then if [[ $(git ls-remote --heads origin rc) ]]; then
echo "::set-output name=rc_branch_exists::1" echo "rc_branch_exists=1" >> $GITHUB_OUTPUT
else else
echo "::set-output name=rc_branch_exists::0" echo "rc_branch_exists=0" >> $GITHUB_OUTPUT
fi fi
if [[ $(git ls-remote --heads origin hotfix-rc) ]]; then if [[ $(git ls-remote --heads origin hotfix-rc) ]]; then
echo "::set-output name=hotfix_branch_exists::1" echo "hotfix_branch_exists=1" >> $GITHUB_OUTPUT
else else
echo "::set-output name=hotfix_branch_exists::0" echo "hotfix_branch_exists=0" >> $GITHUB_OUTPUT
fi fi
shell: bash shell: bash
@@ -62,7 +62,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
variant: ['prod', 'qa'] variant: ["prod", "qa"]
steps: steps:
- name: Setup NuGet - name: Setup NuGet
uses: nuget/setup-nuget@b2bc17b761a1d88cab755a776c7922eb26eefbfa # v1.0.6 uses: nuget/setup-nuget@b2bc17b761a1d88cab755a776c7922eb26eefbfa # v1.0.6
@@ -148,7 +148,17 @@ jobs:
shell: pwsh shell: pwsh
- name: Run Core tests - name: Run Core tests
run: dotnet test test/Core.Test/Core.Test.csproj run: dotnet test test/Core.Test/Core.Test.csproj --logger "trx;LogFileName=test-results.trx" || true
shell: pwsh
- name: Report test results
uses: dorny/test-reporter@c9b3d0e2bd2a4e96aaf424dbaa31c46b42318226
if: always()
with:
name: Test Results
path: "**/test-results.trx"
reporter: dotnet-trx
fail-on-error: true
- name: Build Play Store publisher - name: Build Play Store publisher
if: ${{ matrix.variant == 'prod' }} if: ${{ matrix.variant == 'prod' }}
@@ -440,7 +450,7 @@ jobs:
ios: ios:
name: Apple iOS name: Apple iOS
runs-on: macos-11 runs-on: macos-12
needs: setup needs: setup
steps: steps:
- name: Setup NuGet - name: Setup NuGet
@@ -475,7 +485,7 @@ jobs:
do do
VALUE=$(az keyvault secret show --vault-name $KEYVAULT --name $i --query value --output tsv) VALUE=$(az keyvault secret show --vault-name $KEYVAULT --name $i --query value --output tsv)
echo "::add-mask::$VALUE" echo "::add-mask::$VALUE"
echo "::set-output name=$i::$VALUE" echo "$i=$VALUE" >> $GITHUB_OUTPUT
done done
- name: Decrypt secrets - name: Decrypt secrets
@@ -497,6 +507,14 @@ jobs:
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output $HOME/secrets/dist_share_extension.mobileprovision \ --output $HOME/secrets/dist_share_extension.mobileprovision \
./.github/secrets/dist_share_extension.mobileprovision.gpg ./.github/secrets/dist_share_extension.mobileprovision.gpg
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output $HOME/secrets/dist_watch_app.mobileprovision \
./.github/secrets/dist_watch_app.mobileprovision.gpg
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output $HOME/secrets/dist_watch_app_extension.mobileprovision \
./.github/secrets/dist_watch_app_extension.mobileprovision.gpg
gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \
--output ./src/watchOS/bitwarden/GoogleService-Info.plist ./.github/secrets/GoogleService-Info.plist.gpg
shell: bash shell: bash
- name: Increment version - name: Increment version
@@ -511,6 +529,9 @@ jobs:
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Extension/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Extension/Info.plist
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Autofill/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.Autofill/Info.plist
perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.ShareExtension/Info.plist perl -0777 -pi.bak -e 's/<key>CFBundleVersion<\/key>\s*<string>1<\/string>/<key>CFBundleVersion<\/key>\n\t<string>'"$BUILD_NUMBER"'<\/string>/' ./src/iOS.ShareExtension/Info.plist
cd src/watchOS/bitwarden
agvtool new-version -all $BUILD_NUMBER
cd ../../..
shell: bash shell: bash
- name: Update Entitlements - name: Update Entitlements
@@ -545,6 +566,8 @@ jobs:
BITWARDEN_PROFILE_PATH=$HOME/secrets/dist_bitwarden.mobileprovision BITWARDEN_PROFILE_PATH=$HOME/secrets/dist_bitwarden.mobileprovision
EXTENSION_PROFILE_PATH=$HOME/secrets/dist_extension.mobileprovision EXTENSION_PROFILE_PATH=$HOME/secrets/dist_extension.mobileprovision
SHARE_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_share_extension.mobileprovision SHARE_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_share_extension.mobileprovision
WATCH_APP_PROFILE_PATH=$HOME/secrets/dist_watch_app.mobileprovision
WATCH_APP_EXTENSION_PROFILE_PATH=$HOME/secrets/dist_watch_app_extension.mobileprovision
PROFILES_DIR_PATH=$HOME/Library/MobileDevice/Provisioning\ Profiles PROFILES_DIR_PATH=$HOME/Library/MobileDevice/Provisioning\ Profiles
mkdir -p "$PROFILES_DIR_PATH" mkdir -p "$PROFILES_DIR_PATH"
@@ -560,6 +583,25 @@ jobs:
SHARE_EXTENSION_UUID=$(grep UUID -A1 -a $SHARE_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}") SHARE_EXTENSION_UUID=$(grep UUID -A1 -a $SHARE_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
cp $SHARE_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$SHARE_EXTENSION_UUID.mobileprovision" cp $SHARE_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$SHARE_EXTENSION_UUID.mobileprovision"
WATCH_APP_UUID=$(grep UUID -A1 -a $WATCH_APP_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
cp $WATCH_APP_PROFILE_PATH "$PROFILES_DIR_PATH/$WATCH_APP_UUID.mobileprovision"
WATCH_APP_EXTENSION_UUID=$(grep UUID -A1 -a $WATCH_APP_EXTENSION_PROFILE_PATH | grep -io "[-A-F0-9]\{36\}")
cp $WATCH_APP_EXTENSION_PROFILE_PATH "$PROFILES_DIR_PATH/$WATCH_APP_EXTENSION_UUID.mobileprovision"
shell: bash
- name: Bulid WatchApp
run: |
echo "########################################"
echo "##### Build WatchApp with Release Configuration"
echo "########################################"
xcodebuild archive -workspace ./src/watchOS/bitwarden/bitwarden.xcodeproj/project.xcworkspace -configuration Release -scheme bitwarden\ WatchKit\ App -archivePath ./src/watchOS/bitwarden
echo "########################################"
echo "##### Done"
echo "########################################"
shell: bash shell: bash
- name: Restore packages - name: Restore packages
@@ -597,7 +639,12 @@ jobs:
ARCHIVE_DSYMS_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive/dSYMs" ARCHIVE_DSYMS_PATH="$HOME/Library/Developer/Xcode/Archives/*/*.xcarchive/dSYMs"
EXPORT_PATH="./bitwarden-export" EXPORT_PATH="./bitwarden-export"
cp -r $ARCHIVE_DSYMS_PATH $EXPORT_PATH WATCH_ARCHIVE_DSYMS_PATH="./src/watchOS/bitwarden.xcarchive/dSYMs/"
WATCH_DSYMS_EXPORT_PATH="$EXPORT_PATH/Watch_dSYMs"
cp -r -v $ARCHIVE_DSYMS_PATH $EXPORT_PATH
mkdir $WATCH_DSYMS_EXPORT_PATH
cp -r -v $WATCH_ARCHIVE_DSYMS_PATH $WATCH_DSYMS_EXPORT_PATH
shell: bash shell: bash
- name: Upload App Store .ipa & dSYMs artifacts - name: Upload App Store .ipa & dSYMs artifacts
@@ -630,6 +677,22 @@ jobs:
run: appcenter crashes upload-symbols -a bitwarden/bitwarden -s "./bitwarden-export/dSYMs" --token $APPCENTER_IOS_TOKEN run: appcenter crashes upload-symbols -a bitwarden/bitwarden -s "./bitwarden-export/dSYMs" --token $APPCENTER_IOS_TOKEN
shell: bash shell: bash
- name: Upload Watch dSYMs to Firebase Crashlytics
if: |
(github.ref == 'refs/heads/master'
&& needs.setup.outputs.rc_branch_exists == 0
&& needs.setup.outputs.hotfix_branch_exists == 0)
|| (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0)
|| github.ref == 'refs/heads/hotfix-rc'
run: |
echo "########################################"
echo "##### Uploading Watch dSYMs to Firebase"
echo "########################################"
find "$HOME/Library/Developer/XCode/DerivedData" -name "upload-symbols" -exec chmod +x {} \; -exec {} -gsp "./src/watchOS/bitwarden/GoogleService-Info.plist" -p ios "./bitwarden-export/Watch_dSYMs" \;
shell: bash
- name: Deploy to App Store - name: Deploy to App Store
if: | if: |
(github.ref == 'refs/heads/master' (github.ref == 'refs/heads/master'
@@ -676,7 +739,7 @@ jobs:
do do
VALUE=$(az keyvault secret show --vault-name $KEYVAULT --name $i --query value --output tsv) VALUE=$(az keyvault secret show --vault-name $KEYVAULT --name $i --query value --output tsv)
echo "::add-mask::$VALUE" echo "::add-mask::$VALUE"
echo "::set-output name=$i::$VALUE" echo "$i=$VALUE" >> $GITHUB_OUTPUT
done done
- name: Upload Sources - name: Upload Sources
@@ -744,7 +807,7 @@ jobs:
do do
VALUE=$(az keyvault secret show --vault-name $KEYVAULT --name $i --query value --output tsv) VALUE=$(az keyvault secret show --vault-name $KEYVAULT --name $i --query value --output tsv)
echo "::add-mask::$VALUE" echo "::add-mask::$VALUE"
echo "::set-output name=$i::$VALUE" echo "$i=$VALUE" >> $GITHUB_OUTPUT
done done
- name: Notify Slack on failure - name: Notify Slack on failure

View File

@@ -12,5 +12,5 @@ jobs:
- name: Enforce Label - name: Enforce Label
uses: yogevbd/enforce-label-action@8d1e1709b1011e6d90400a0e6cf7c0b77aa5efeb uses: yogevbd/enforce-label-action@8d1e1709b1011e6d90400a0e6cf7c0b77aa5efeb
with: with:
BANNED_LABELS: "hold" BANNED_LABELS: "hold,needs-qa"
BANNED_LABELS_DESCRIPTION: "PRs on hold cannot be merged" BANNED_LABELS_DESCRIPTION: "PRs with the hold or needs-qa labels cannot be merged"

View File

@@ -1,5 +1,6 @@
--- ---
name: Release name: Release
run-name: Release ${{ inputs.release_type }}
on: on:
workflow_dispatch: workflow_dispatch:
@@ -51,9 +52,10 @@ jobs:
id: branch id: branch
run: | run: |
BRANCH_NAME=$(basename ${{ github.ref }}) BRANCH_NAME=$(basename ${{ github.ref }})
echo "::set-output name=branch-name::$BRANCH_NAME" echo "branch-name=$BRANCH_NAME" >> $GITHUB_OUTPUT
- name: Create GitHub deployment - name: Create GitHub deployment
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
uses: chrnorm/deployment-action@1b599fe41a0ef1f95191e7f2eec4743f2d7dfc48 uses: chrnorm/deployment-action@1b599fe41a0ef1f95191e7f2eec4743f2d7dfc48
id: deployment id: deployment
with: with:
@@ -72,7 +74,7 @@ jobs:
workflow_conclusion: success workflow_conclusion: success
branch: ${{ steps.branch.outputs.branch-name }} branch: ${{ steps.branch.outputs.branch-name }}
- name: Download all artifacts - name: Dry Run - Download all artifacts
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: dawidd6/action-download-artifact@575b1e4167df67acf7e692af784566618b23c71e # v2.17.10 uses: dawidd6/action-download-artifact@575b1e4167df67acf7e692af784566618b23c71e # v2.17.10
with: with:
@@ -99,7 +101,7 @@ jobs:
draft: true draft: true
- name: Update deployment status to Success - name: Update deployment status to Success
if: ${{ success() }} if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }}
uses: chrnorm/deployment-status@07b3930847f65e71c9c6802ff5a402f6dfb46b86 uses: chrnorm/deployment-status@07b3930847f65e71c9c6802ff5a402f6dfb46b86
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
@@ -107,7 +109,7 @@ jobs:
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: ${{ failure() }} if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }}
uses: chrnorm/deployment-status@07b3930847f65e71c9c6802ff5a402f6dfb46b86 uses: chrnorm/deployment-status@07b3930847f65e71c9c6802ff5a402f6dfb46b86
with: with:
token: '${{ secrets.GITHUB_TOKEN }}' token: '${{ secrets.GITHUB_TOKEN }}'
@@ -133,7 +135,7 @@ jobs:
branch: ${{ needs.release.outputs.branch-name }} branch: ${{ needs.release.outputs.branch-name }}
name: com.x8bit.bitwarden-fdroid.apk name: com.x8bit.bitwarden-fdroid.apk
- name: Download F-Droid .apk artifact - name: Dry Run - Download F-Droid .apk artifact
if: ${{ github.event.inputs.release_type == 'Dry Run' }} if: ${{ github.event.inputs.release_type == 'Dry Run' }}
uses: dawidd6/action-download-artifact@575b1e4167df67acf7e692af784566618b23c71e # v2.17.10 uses: dawidd6/action-download-artifact@575b1e4167df67acf7e692af784566618b23c71e # v2.17.10
with: with:

View File

@@ -21,15 +21,15 @@ jobs:
env: env:
RELEASE_TAG: ${{ github.ref }} RELEASE_TAG: ${{ github.ref }}
run: | run: |
CURR_MAJOR=$(echo $RELEASE_TAG | sed -r 's/v([0-9]{4}\.[0-9]{1,2})\.([0-9]{1,2})/\1/') CURR_MAJOR=$(echo $RELEASE_TAG | sed -r 's/refs\/tags\/v([0-9]{4}\.[0-9]{1,2})\.([0-9]{1,2})/\1/')
CURR_PATCH=$(echo $RELEASE_TAG | sed -r 's/v([0-9]{4}\.[0-9]{1,2})\.([0-9]{1,2})/\2/') CURR_PATCH=$(echo $RELEASE_TAG | sed -r 's/refs\/tags\/v([0-9]{4}\.[0-9]{1,2})\.([0-9]{1,2})/\2/')
echo "Current Major: $CURR_MAJOR" echo "Current Major: $CURR_MAJOR"
echo "Current Patch: $CURR_PATCH" echo "Current Patch: $CURR_PATCH"
NEW_PATCH=$((CURR_PATCH+1)) NEW_PATCH=$((CURR_PATCH+1))
NEW_VER=$CURR_MAJOR.$NEW_PATCH NEW_VER=$CURR_MAJOR.$NEW_PATCH
echo "New Version: $NEW_VER" echo "New Version: $NEW_VER"
echo "::set-output name=new-version::$NEW_VER" echo "new-version=$NEW_VER" >> $GITHUB_OUTPUT
trigger_version_bump: trigger_version_bump:
name: "Trigger version bump workflow" name: "Trigger version bump workflow"

View File

@@ -37,8 +37,7 @@ jobs:
git_commit_gpgsign: true git_commit_gpgsign: true
- name: Create Version Branch - name: Create Version Branch
run: | run: git switch -c version_bump_${{ github.event.inputs.version_number }}
git switch -c version_bump_${{ github.event.inputs.version_number }}
- name: Bump Version - Android XML - name: Bump Version - Android XML
uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945 uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945
@@ -79,16 +78,15 @@ jobs:
id: version-changed id: version-changed
run: | run: |
if [ -n "$(git status --porcelain)" ]; then if [ -n "$(git status --porcelain)" ]; then
echo "::set-output name=changes_to_commit::TRUE" echo "changes_to_commit=TRUE" >> $GITHUB_OUTPUT
else else
echo "::set-output name=changes_to_commit::FALSE" echo "changes_to_commit=FALSE" >> $GITHUB_OUTPUT
echo "No changes to commit!"; echo "No changes to commit!";
fi fi
- name: Commit files - name: Commit files
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
run: | run: git commit -m "Bumped version to ${{ github.event.inputs.version_number }}" -a
git commit -m "Bumped version to ${{ github.event.inputs.version_number }}" -a
- name: Push changes - name: Push changes
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}

125
.gitignore vendored
View File

@@ -210,3 +210,128 @@ project.lock.json
.DS_Store .DS_Store
src/App/Css src/App/Css
tools tools
# Created by https://www.toptal.com/developers/gitignore/api/swift,objective-c
# Edit at https://www.toptal.com/developers/gitignore?templates=swift,objective-c
### Objective-C ###
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## User settings
xcuserdata/
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
## Obj-C/Swift specific
*.hmap
## App packaging
*.ipa
*.dSYM.zip
*.dSYM
# CocoaPods
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
# Pods/
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace
# Carthage
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build/
# fastlane
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output
# Code Injection
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
iOSInjectionProject/
### Objective-C Patch ###
### Swift ###
# Xcode
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Playgrounds
timeline.xctimeline
playground.xcworkspace
# Swift Package Manager
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
# Package.resolved
# *.xcodeproj
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm
.build/
# CocoaPods
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
# Pods/
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace
# Carthage
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
# Accio dependency management
Dependencies/
.accio/
# fastlane
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control
# Code Injection
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode
# End of https://www.toptal.com/developers/gitignore/api/swift,objective-c

View File

@@ -12,7 +12,7 @@ The Bitwarden mobile application is written in C# with Xamarin Android, Xamarin
# Build/Run # Build/Run
Please refer to the [Mobile section](https://contributing.bitwarden.com/mobile/) of the [Contributing Documentation](https://contributing.bitwarden.com/) for build instructions, recommended tooling, code style tips, and lots of other great information to get you started. Please refer to the [Mobile section](https://contributing.bitwarden.com/getting-started/clients/mobile/) of the [Contributing Documentation](https://contributing.bitwarden.com/) for build instructions, recommended tooling, code style tips, and lots of other great information to get you started.
# We're Hiring! # We're Hiring!

View File

@@ -132,6 +132,7 @@ Task("UpdateAndroidCodeFiles")
Path.Combine(_slnPath, "src", "Android", "Receivers", "PackageReplacedReceiver.cs"), Path.Combine(_slnPath, "src", "Android", "Receivers", "PackageReplacedReceiver.cs"),
Path.Combine(_slnPath, "src", "Android", "Receivers", "RestrictionsChangedReceiver.cs"), Path.Combine(_slnPath, "src", "Android", "Receivers", "RestrictionsChangedReceiver.cs"),
Path.Combine(_slnPath, "src", "Android", "Services", "DeviceActionService.cs"), Path.Combine(_slnPath, "src", "Android", "Services", "DeviceActionService.cs"),
Path.Combine(_slnPath, "src", "Android", "Services", "FileService.cs"),
Path.Combine(_slnPath, "src", "Android", "Tiles", "AutofillTileService.cs"), Path.Combine(_slnPath, "src", "Android", "Tiles", "AutofillTileService.cs"),
Path.Combine(_slnPath, "src", "Android", "Tiles", "GeneratorTileService.cs"), Path.Combine(_slnPath, "src", "Android", "Tiles", "GeneratorTileService.cs"),
Path.Combine(_slnPath, "src", "Android", "Tiles", "MyVaultTileService.cs"), Path.Combine(_slnPath, "src", "Android", "Tiles", "MyVaultTileService.cs"),

View File

@@ -33,6 +33,7 @@ namespace Bit.Droid.Accessibility
// - Resources/xml/autofillservice.xml // - Resources/xml/autofillservice.xml
new Browser("alook.browser", "search_fragment_input_view"), new Browser("alook.browser", "search_fragment_input_view"),
new Browser("alook.browser.google", "search_fragment_input_view"), new Browser("alook.browser.google", "search_fragment_input_view"),
new Browser("app.vanadium.browser", "url_bar"),
new Browser("com.amazon.cloud9", "url"), new Browser("com.amazon.cloud9", "url"),
new Browser("com.android.browser", "url"), new Browser("com.android.browser", "url"),
new Browser("com.android.chrome", "url_bar"), new Browser("com.android.chrome", "url_bar"),
@@ -66,6 +67,7 @@ namespace Bit.Droid.Accessibility
new Browser("com.mmbox.xbrowser", "search_box"), new Browser("com.mmbox.xbrowser", "search_box"),
new Browser("com.mycompany.app.soulbrowser", "edit_text"), new Browser("com.mycompany.app.soulbrowser", "edit_text"),
new Browser("com.naver.whale", "url_bar"), new Browser("com.naver.whale", "url_bar"),
new Browser("com.neeva.app", "full_url_text_view"),
new Browser("com.opera.browser", "url_field"), new Browser("com.opera.browser", "url_field"),
new Browser("com.opera.browser.beta", "url_field"), new Browser("com.opera.browser.beta", "url_field"),
new Browser("com.opera.gx", "addressbarEdit"), new Browser("com.opera.gx", "addressbarEdit"),
@@ -74,6 +76,7 @@ namespace Bit.Droid.Accessibility
new Browser("com.opera.touch", "addressbarEdit"), new Browser("com.opera.touch", "addressbarEdit"),
new Browser("com.qflair.browserq", "url"), new Browser("com.qflair.browserq", "url"),
new Browser("com.qwant.liberty", "mozac_browser_toolbar_url_view,url_bar_title"), // 2nd = Legacy (before v4) new Browser("com.qwant.liberty", "mozac_browser_toolbar_url_view,url_bar_title"), // 2nd = Legacy (before v4)
new Browser("com.rainsee.create", "search_box"),
new Browser("com.sec.android.app.sbrowser", "location_bar_edit_text"), new Browser("com.sec.android.app.sbrowser", "location_bar_edit_text"),
new Browser("com.sec.android.app.sbrowser.beta", "location_bar_edit_text"), new Browser("com.sec.android.app.sbrowser.beta", "location_bar_edit_text"),
new Browser("com.stoutner.privacybrowser.free", "url_edittext"), new Browser("com.stoutner.privacybrowser.free", "url_edittext"),
@@ -83,6 +86,9 @@ namespace Bit.Droid.Accessibility
new Browser("com.vivaldi.browser.sopranos", "url_bar"), new Browser("com.vivaldi.browser.sopranos", "url_bar"),
new Browser("com.yandex.browser", "bro_omnibar_address_title_text,bro_omnibox_collapsed_title", new Browser("com.yandex.browser", "bro_omnibar_address_title_text,bro_omnibox_collapsed_title",
(s) => s.Split(new char[]{' ', ' '}).FirstOrDefault()), // 0 = Regular Space, 1 = No-break space (00A0) (s) => s.Split(new char[]{' ', ' '}).FirstOrDefault()), // 0 = Regular Space, 1 = No-break space (00A0)
new Browser("com.yjllq.internet", "search_box"),
new Browser("com.yjllq.kito", "search_box"),
new Browser("com.yujian.ResideMenuDemo", "search_box"),
new Browser("com.z28j.feel", "g2"), new Browser("com.z28j.feel", "g2"),
new Browser("idm.internet.download.manager", "search"), new Browser("idm.internet.download.manager", "search"),
new Browser("idm.internet.download.manager.adm.lite", "search"), new Browser("idm.internet.download.manager.adm.lite", "search"),
@@ -90,6 +96,7 @@ namespace Bit.Droid.Accessibility
new Browser("io.github.forkmaintainers.iceraven", "mozac_browser_toolbar_url_view"), new Browser("io.github.forkmaintainers.iceraven", "mozac_browser_toolbar_url_view"),
new Browser("mark.via", "am,an"), new Browser("mark.via", "am,an"),
new Browser("mark.via.gp", "as"), new Browser("mark.via.gp", "as"),
new Browser("net.dezor.browser", "url_bar"),
new Browser("net.slions.fulguris.full.download", "search"), new Browser("net.slions.fulguris.full.download", "search"),
new Browser("net.slions.fulguris.full.download.debug", "search"), new Browser("net.slions.fulguris.full.download.debug", "search"),
new Browser("net.slions.fulguris.full.playstore", "search"), new Browser("net.slions.fulguris.full.playstore", "search"),
@@ -129,6 +136,7 @@ namespace Bit.Droid.Accessibility
new Browser("com.htc.sense.browser", "title"), new Browser("com.htc.sense.browser", "title"),
new Browser("com.jerky.browser2", "enterUrl"), new Browser("com.jerky.browser2", "enterUrl"),
new Browser("com.ksmobile.cb", "address_bar_edit_text"), new Browser("com.ksmobile.cb", "address_bar_edit_text"),
new Browser("com.lemurbrowser.exts","url_bar"),
new Browser("com.linkbubble.playstore", "url_text"), new Browser("com.linkbubble.playstore", "url_text"),
new Browser("com.mx.browser", "address_editor_with_progress"), new Browser("com.mx.browser", "address_editor_with_progress"),
new Browser("com.mx.browser.tablet", "address_editor_with_progress"), new Browser("com.mx.browser.tablet", "address_editor_with_progress"),

View File

@@ -15,7 +15,7 @@
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest> <AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix> <MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix> <MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
<TargetFrameworkVersion>v12.1</TargetFrameworkVersion> <TargetFrameworkVersion>v13.0</TargetFrameworkVersion>
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType> <AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
<NuGetPackageImportStamp> <NuGetPackageImportStamp>
</NuGetPackageImportStamp> </NuGetPackageImportStamp>
@@ -77,12 +77,12 @@
<PackageReference Include="Portable.BouncyCastle"> <PackageReference Include="Portable.BouncyCastle">
<Version>1.9.0</Version> <Version>1.9.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.5.1" /> <PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.5.1.1" />
<PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.13" /> <PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.14" />
<PackageReference Include="Xamarin.AndroidX.CardView" Version="1.0.0.16" /> <PackageReference Include="Xamarin.AndroidX.CardView" Version="1.0.0.17" />
<PackageReference Include="Xamarin.AndroidX.Core" Version="1.9.0" /> <PackageReference Include="Xamarin.AndroidX.Core" Version="1.9.0.1" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.14" /> <PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.15" />
<PackageReference Include="Xamarin.AndroidX.MediaRouter" Version="1.3.1" /> <PackageReference Include="Xamarin.AndroidX.MediaRouter" Version="1.3.1.1" />
<PackageReference Include="Xamarin.Essentials"> <PackageReference Include="Xamarin.Essentials">
<Version>1.7.3</Version> <Version>1.7.3</Version>
</PackageReference> </PackageReference>
@@ -103,8 +103,10 @@
<Compile Include="Accessibility\Browser.cs" /> <Compile Include="Accessibility\Browser.cs" />
<Compile Include="Accessibility\NodeList.cs" /> <Compile Include="Accessibility\NodeList.cs" />
<Compile Include="Accessibility\KnownUsernameField.cs" /> <Compile Include="Accessibility\KnownUsernameField.cs" />
<Compile Include="Autofill\AutofillConstants.cs" />
<Compile Include="Autofill\AutofillHelpers.cs" /> <Compile Include="Autofill\AutofillHelpers.cs" />
<Compile Include="Autofill\AutofillService.cs" /> <Compile Include="Autofill\AutofillService.cs" />
<Compile Include="Autofill\AutofillExternalSelectionActivity.cs" />
<Compile Include="Autofill\Field.cs" /> <Compile Include="Autofill\Field.cs" />
<Compile Include="Autofill\FieldCollection.cs" /> <Compile Include="Autofill\FieldCollection.cs" />
<Compile Include="Autofill\FilledItem.cs" /> <Compile Include="Autofill\FilledItem.cs" />
@@ -157,6 +159,7 @@
<Compile Include="Services\AutofillHandler.cs" /> <Compile Include="Services\AutofillHandler.cs" />
<Compile Include="Constants.cs" /> <Compile Include="Constants.cs" />
<Compile Include="Effects\RemoveFontPaddingEffect.cs" /> <Compile Include="Effects\RemoveFontPaddingEffect.cs" />
<Compile Include="Services\WatchDeviceService.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<AndroidAsset Include="Assets\bwi-font.ttf" /> <AndroidAsset Include="Assets\bwi-font.ttf" />

View File

@@ -0,0 +1,10 @@
namespace Bit.Droid.Autofill
{
public class AutofillConstants
{
public const string AutofillFramework = "autofillFramework";
public const string AutofillFrameworkFillType = "autofillFrameworkFillType";
public const string AutofillFrameworkUri = "autofillFrameworkUri";
public const string AutofillFrameworkCipherId = "autofillFrameworkCipherId";
}
}

View File

@@ -0,0 +1,42 @@
using System.Threading.Tasks;
using Android.App;
using Android.Content.PM;
using Android.OS;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using Bit.Droid.Utilities;
namespace Bit.Droid.Autofill
{
[Activity(
NoHistory = true,
LaunchMode = LaunchMode.SingleTop)]
public class AutofillExternalSelectionActivity : Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
Intent?.Validate();
base.OnCreate(bundle);
var cipherId = Intent?.GetStringExtra(AutofillConstants.AutofillFrameworkCipherId);
if (string.IsNullOrEmpty(cipherId))
{
SetResult(Result.Canceled);
Finish();
return;
}
GetCipherAndPerformAutofillAsync(cipherId).FireAndForget();
}
private async Task GetCipherAndPerformAutofillAsync(string cipherId)
{
var cipherService = ServiceContainer.Resolve<ICipherService>();
var cipher = await cipherService.GetAsync(cipherId);
var decCipher = await cipher.DecryptAsync();
var autofillHandler = ServiceContainer.Resolve<IAutofillHandler>();
autofillHandler.Autofill(decCipher);
}
}
}

View File

@@ -54,6 +54,7 @@ namespace Bit.Droid.Autofill
{ {
"alook.browser", "alook.browser",
"alook.browser.google", "alook.browser.google",
"app.vanadium.browser",
"com.amazon.cloud9", "com.amazon.cloud9",
"com.android.browser", "com.android.browser",
"com.android.chrome", "com.android.chrome",
@@ -78,6 +79,7 @@ namespace Bit.Droid.Autofill
"com.jamal2367.styx", "com.jamal2367.styx",
"com.kiwibrowser.browser", "com.kiwibrowser.browser",
"com.kiwibrowser.browser.dev", "com.kiwibrowser.browser.dev",
"com.lemurbrowser.exts",
"com.microsoft.emmx", "com.microsoft.emmx",
"com.microsoft.emmx.beta", "com.microsoft.emmx.beta",
"com.microsoft.emmx.canary", "com.microsoft.emmx.canary",
@@ -86,6 +88,7 @@ namespace Bit.Droid.Autofill
"com.mmbox.xbrowser", "com.mmbox.xbrowser",
"com.mycompany.app.soulbrowser", "com.mycompany.app.soulbrowser",
"com.naver.whale", "com.naver.whale",
"com.neeva.app",
"com.opera.browser", "com.opera.browser",
"com.opera.browser.beta", "com.opera.browser.beta",
"com.opera.gx", "com.opera.gx",
@@ -94,6 +97,7 @@ namespace Bit.Droid.Autofill
"com.opera.touch", "com.opera.touch",
"com.qflair.browserq", "com.qflair.browserq",
"com.qwant.liberty", "com.qwant.liberty",
"com.rainsee.create",
"com.sec.android.app.sbrowser", "com.sec.android.app.sbrowser",
"com.sec.android.app.sbrowser.beta", "com.sec.android.app.sbrowser.beta",
"com.stoutner.privacybrowser.free", "com.stoutner.privacybrowser.free",
@@ -102,6 +106,9 @@ namespace Bit.Droid.Autofill
"com.vivaldi.browser.snapshot", "com.vivaldi.browser.snapshot",
"com.vivaldi.browser.sopranos", "com.vivaldi.browser.sopranos",
"com.yandex.browser", "com.yandex.browser",
"com.yjllq.internet",
"com.yjllq.kito",
"com.yujian.ResideMenuDemo",
"com.z28j.feel", "com.z28j.feel",
"idm.internet.download.manager", "idm.internet.download.manager",
"idm.internet.download.manager.adm.lite", "idm.internet.download.manager.adm.lite",
@@ -109,6 +116,7 @@ namespace Bit.Droid.Autofill
"io.github.forkmaintainers.iceraven", "io.github.forkmaintainers.iceraven",
"mark.via", "mark.via",
"mark.via.gp", "mark.via.gp",
"net.dezor.browser",
"net.slions.fulguris.full.download", "net.slions.fulguris.full.download",
"net.slions.fulguris.full.download.debug", "net.slions.fulguris.full.download.debug",
"net.slions.fulguris.full.playstore", "net.slions.fulguris.full.playstore",
@@ -207,7 +215,7 @@ namespace Bit.Droid.Autofill
} }
} }
var dataset = BuildDataset(parser.ApplicationContext, parser.FieldCollection, items[i], var dataset = BuildDataset(parser.ApplicationContext, parser.FieldCollection, items[i],
inlinePresentationSpec); true, inlinePresentationSpec);
if (dataset != null) if (dataset != null)
{ {
responseBuilder.AddDataset(dataset); responseBuilder.AddDataset(dataset);
@@ -221,7 +229,7 @@ namespace Bit.Droid.Autofill
} }
public static Dataset BuildDataset(Context context, FieldCollection fields, FilledItem filledItem, public static Dataset BuildDataset(Context context, FieldCollection fields, FilledItem filledItem,
InlinePresentationSpec inlinePresentationSpec = null) bool includeAuthIntent, InlinePresentationSpec inlinePresentationSpec = null)
{ {
var overlayPresentation = BuildOverlayPresentation( var overlayPresentation = BuildOverlayPresentation(
filledItem.Name, filledItem.Name,
@@ -242,6 +250,15 @@ namespace Bit.Droid.Autofill
{ {
datasetBuilder.SetInlinePresentation(inlinePresentation); datasetBuilder.SetInlinePresentation(inlinePresentation);
} }
if (includeAuthIntent)
{
var intent = new Intent(context, typeof(AutofillExternalSelectionActivity));
intent.PutExtra(AutofillConstants.AutofillFramework, true);
intent.PutExtra(AutofillConstants.AutofillFrameworkCipherId, filledItem.Id);
var pendingIntent = PendingIntent.GetActivity(context, ++_pendingIntentId, intent,
AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.CancelCurrent, true));
datasetBuilder.SetAuthentication(pendingIntent?.IntentSender);
}
if (filledItem.ApplyToFields(fields, datasetBuilder)) if (filledItem.ApplyToFields(fields, datasetBuilder))
{ {
return datasetBuilder.Build(); return datasetBuilder.Build();
@@ -253,25 +270,26 @@ namespace Bit.Droid.Autofill
IList<InlinePresentationSpec> inlinePresentationSpecs = null) IList<InlinePresentationSpec> inlinePresentationSpecs = null)
{ {
var intent = new Intent(context, typeof(MainActivity)); var intent = new Intent(context, typeof(MainActivity));
intent.PutExtra("autofillFramework", true); intent.PutExtra(AutofillConstants.AutofillFramework, true);
if (fields.FillableForLogin) if (fields.FillableForLogin)
{ {
intent.PutExtra("autofillFrameworkFillType", (int)CipherType.Login); intent.PutExtra(AutofillConstants.AutofillFrameworkFillType, (int)CipherType.Login);
} }
else if (fields.FillableForCard) else if (fields.FillableForCard)
{ {
intent.PutExtra("autofillFrameworkFillType", (int)CipherType.Card); intent.PutExtra(AutofillConstants.AutofillFrameworkFillType, (int)CipherType.Card);
} }
else if (fields.FillableForIdentity) else if (fields.FillableForIdentity)
{ {
intent.PutExtra("autofillFrameworkFillType", (int)CipherType.Identity); intent.PutExtra(AutofillConstants.AutofillFrameworkFillType, (int)CipherType.Identity);
} }
else else
{ {
return null; return null;
} }
intent.PutExtra("autofillFrameworkUri", uri); intent.PutExtra(AutofillConstants.AutofillFrameworkUri, uri);
var pendingIntent = PendingIntent.GetActivity(context, ++_pendingIntentId, intent, AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.CancelCurrent, true)); var pendingIntent = PendingIntent.GetActivity(context, ++_pendingIntentId, intent,
AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.CancelCurrent, true));
var overlayPresentation = BuildOverlayPresentation( var overlayPresentation = BuildOverlayPresentation(
AppResources.AutofillWithBitwarden, AppResources.AutofillWithBitwarden,

View File

@@ -23,6 +23,7 @@ namespace Bit.Droid.Autofill
public FilledItem(CipherView cipher) public FilledItem(CipherView cipher)
{ {
Id = cipher.Id;
Name = cipher.Name; Name = cipher.Name;
Type = cipher.Type; Type = cipher.Type;
Subtitle = cipher.SubTitle; Subtitle = cipher.SubTitle;
@@ -55,6 +56,7 @@ namespace Bit.Droid.Autofill
} }
} }
public string Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string Subtitle { get; set; } = string.Empty; public string Subtitle { get; set; } = string.Empty;
public int Icon { get; set; } = Resource.Drawable.login; public int Icon { get; set; } = Resource.Drawable.login;

View File

@@ -18,6 +18,7 @@ using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Bit.Droid.Autofill;
using Bit.Droid.Receivers; using Bit.Droid.Receivers;
using Bit.Droid.Utilities; using Bit.Droid.Utilities;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -322,13 +323,13 @@ namespace Bit.Droid
{ {
var options = new AppOptions var options = new AppOptions
{ {
Uri = Intent.GetStringExtra("uri") ?? Intent.GetStringExtra("autofillFrameworkUri"), Uri = Intent.GetStringExtra("uri") ?? Intent.GetStringExtra(AutofillConstants.AutofillFrameworkUri),
MyVaultTile = Intent.GetBooleanExtra("myVaultTile", false), MyVaultTile = Intent.GetBooleanExtra("myVaultTile", false),
GeneratorTile = Intent.GetBooleanExtra("generatorTile", false), GeneratorTile = Intent.GetBooleanExtra("generatorTile", false),
FromAutofillFramework = Intent.GetBooleanExtra("autofillFramework", false), FromAutofillFramework = Intent.GetBooleanExtra(AutofillConstants.AutofillFramework, false),
CreateSend = GetCreateSendRequest(Intent) CreateSend = GetCreateSendRequest(Intent)
}; };
var fillType = Intent.GetIntExtra("autofillFrameworkFillType", 0); var fillType = Intent.GetIntExtra(AutofillConstants.AutofillFrameworkFillType, 0);
if (fillType > 0) if (fillType > 0)
{ {
options.FillType = (CipherType)fillType; options.FillType = (CipherType)fillType;

View File

@@ -45,9 +45,16 @@ namespace Bit.Droid
if (ServiceContainer.RegisteredServices.Count == 0) if (ServiceContainer.RegisteredServices.Count == 0)
{ {
RegisterLocalServices(); RegisterLocalServices();
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService"); var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
ServiceContainer.Init(deviceActionService.DeviceUserAgent, Core.Constants.ClearCiphersCacheKey, ServiceContainer.Init(deviceActionService.DeviceUserAgent, Core.Constants.ClearCiphersCacheKey,
Core.Constants.AndroidAllClearCipherCacheKeys); Core.Constants.AndroidAllClearCipherCacheKeys);
ServiceContainer.Register<IWatchDeviceService>(new WatchDeviceService(ServiceContainer.Resolve<ICipherService>(),
ServiceContainer.Resolve<IEnvironmentService>(),
ServiceContainer.Resolve<IStateService>(),
ServiceContainer.Resolve<IVaultTimeoutService>()));
InitializeAppSetup(); InitializeAppSetup();
// TODO: Update when https://github.com/bitwarden/mobile/pull/1662 gets merged // TODO: Update when https://github.com/bitwarden/mobile/pull/1662 gets merged
@@ -73,7 +80,8 @@ namespace Bit.Droid
ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"), ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"),
ServiceContainer.Resolve<IAuthService>("authService"), ServiceContainer.Resolve<IAuthService>("authService"),
ServiceContainer.Resolve<ILogger>("logger"), ServiceContainer.Resolve<ILogger>("logger"),
ServiceContainer.Resolve<IMessagingService>("messagingService")); ServiceContainer.Resolve<IMessagingService>("messagingService"),
ServiceContainer.Resolve<IWatchDeviceService>());
ServiceContainer.Register<IAccountsManager>("accountsManager", accountsManager); ServiceContainer.Register<IAccountsManager>("accountsManager", accountsManager);
} }
#if !FDROID #if !FDROID
@@ -141,9 +149,10 @@ namespace Bit.Droid
var clipboardService = new ClipboardService(stateService); var clipboardService = new ClipboardService(stateService);
var deviceActionService = new DeviceActionService(stateService, messagingService); var deviceActionService = new DeviceActionService(stateService, messagingService);
var fileService = new FileService(stateService, broadcasterService); var fileService = new FileService(stateService, broadcasterService);
var autofillHandler = new AutofillHandler(stateService, messagingService, clipboardService, new LazyResolve<IEventService>());
var platformUtilsService = new MobilePlatformUtilsService(deviceActionService, clipboardService, var platformUtilsService = new MobilePlatformUtilsService(deviceActionService, clipboardService,
messagingService, broadcasterService); messagingService, broadcasterService);
var autofillHandler = new AutofillHandler(stateService, messagingService, clipboardService,
platformUtilsService, new LazyResolve<IEventService>());
var biometricService = new BiometricService(); var biometricService = new BiometricService();
var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService); var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService);
var cryptoService = new CryptoService(stateService, cryptoFunctionService); var cryptoService = new CryptoService(stateService, cryptoFunctionService);

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2022.11.0" android:installLocation="internalOnly" package="com.x8bit.bitwarden"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2023.1.1" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="32" /> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -40,10 +40,16 @@
</intent-filter> </intent-filter>
</activity> </activity>
</application> </application>
<!-- Package visibility (for Android 11+) --> <!-- Support for Xamarin.Essentials.Browser.OpenAsync (for Android > 11) -->
<!-- Related docs: https://learn.microsoft.com/en-us/xamarin/essentials/open-browser?tabs=android -->
<queries> <queries>
<intent> <intent>
<action android:name="*" /> <action android:name="android.intent.action.VIEW" />
<data android:scheme="http"/>
</intent>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https"/>
</intent> </intent>
</queries> </queries>
</manifest> </manifest>

View File

@@ -1,4 +1,5 @@
using Android.Content; using Android.Content;
using Android.OS;
namespace Bit.Droid.Receivers namespace Bit.Droid.Receivers
{ {
@@ -8,7 +9,17 @@ namespace Bit.Droid.Receivers
public override void OnReceive(Context context, Intent intent) public override void OnReceive(Context context, Intent intent)
{ {
var clipboardManager = context.GetSystemService(Context.ClipboardService) as ClipboardManager; var clipboardManager = context.GetSystemService(Context.ClipboardService) as ClipboardManager;
if (clipboardManager == null)
{
return;
}
// ClearPrimaryClip is supported down to API 28 with mixed results, so we're requiring 33+ instead
if ((int)Build.VERSION.SdkInt < 33)
{
clipboardManager.PrimaryClip = ClipData.NewPlainText("bitwarden", " "); clipboardManager.PrimaryClip = ClipData.NewPlainText("bitwarden", " ");
return;
}
clipboardManager.ClearPrimaryClip();
} }
} }
} }

View File

@@ -44,6 +44,7 @@ namespace Bit.Droid.Renderers
} }
if (Control != null) if (Control != null)
{ {
Control.SetHintTextColor(ThemeHelpers.MutedColor);
var t = ResourcesCompat.GetDrawable(Resources, Resource.Drawable.switch_thumb, null); var t = ResourcesCompat.GetDrawable(Resources, Resource.Drawable.switch_thumb, null);
if (t is GradientDrawable thumb) if (t is GradientDrawable thumb)
{ {

View File

@@ -17,6 +17,9 @@
<compatibility-package <compatibility-package
android:name="alook.browser.google" android:name="alook.browser.google"
android:maxLongVersionCode="10000000000"/> android:maxLongVersionCode="10000000000"/>
<compatibility-package
android:name="app.vanadium.browser"
android:maxLongVersionCode="10000000000"/>
<compatibility-package <compatibility-package
android:name="com.amazon.cloud9" android:name="com.amazon.cloud9"
android:maxLongVersionCode="10000000000"/> android:maxLongVersionCode="10000000000"/>
@@ -89,6 +92,9 @@
<compatibility-package <compatibility-package
android:name="com.kiwibrowser.browser.dev" android:name="com.kiwibrowser.browser.dev"
android:maxLongVersionCode="10000000000"/> android:maxLongVersionCode="10000000000"/>
<compatibility-package
android:name="com.lemurbrowser.exts"
android:maxLongVersionCode="10000000000"/>
<compatibility-package <compatibility-package
android:name="com.microsoft.emmx" android:name="com.microsoft.emmx"
android:maxLongVersionCode="10000000000"/> android:maxLongVersionCode="10000000000"/>
@@ -113,6 +119,9 @@
<compatibility-package <compatibility-package
android:name="com.naver.whale" android:name="com.naver.whale"
android:maxLongVersionCode="10000000000"/> android:maxLongVersionCode="10000000000"/>
<compatibility-package
android:name="com.neeva.app"
android:maxLongVersionCode="10000000000"/>
<compatibility-package <compatibility-package
android:name="com.opera.browser" android:name="com.opera.browser"
android:maxLongVersionCode="10000000000"/> android:maxLongVersionCode="10000000000"/>
@@ -137,6 +146,9 @@
<compatibility-package <compatibility-package
android:name="com.qwant.liberty" android:name="com.qwant.liberty"
android:maxLongVersionCode="10000000000"/> android:maxLongVersionCode="10000000000"/>
<compatibility-package
android:name="com.rainsee.create"
android:maxLongVersionCode="10000000000"/>
<compatibility-package <compatibility-package
android:name="com.sec.android.app.sbrowser" android:name="com.sec.android.app.sbrowser"
android:maxLongVersionCode="10000000000"/> android:maxLongVersionCode="10000000000"/>
@@ -161,6 +173,15 @@
<compatibility-package <compatibility-package
android:name="com.yandex.browser" android:name="com.yandex.browser"
android:maxLongVersionCode="10000000000"/> android:maxLongVersionCode="10000000000"/>
<compatibility-package
android:name="com.yjllq.internet"
android:maxLongVersionCode="10000000000"/>
<compatibility-package
android:name="com.yjllq.kito"
android:maxLongVersionCode="10000000000"/>
<compatibility-package
android:name="com.yujian.ResideMenuDemo"
android:maxLongVersionCode="10000000000"/>
<compatibility-package <compatibility-package
android:name="com.z28j.feel" android:name="com.z28j.feel"
android:maxLongVersionCode="10000000000"/> android:maxLongVersionCode="10000000000"/>
@@ -182,6 +203,9 @@
<compatibility-package <compatibility-package
android:name="mark.via.gp" android:name="mark.via.gp"
android:maxLongVersionCode="10000000000"/> android:maxLongVersionCode="10000000000"/>
<compatibility-package
android:name="net.dezor.browser"
android:maxLongVersionCode="10000000000"/>
<compatibility-package <compatibility-package
android:name="net.slions.fulguris.full.download" android:name="net.slions.fulguris.full.download"
android:maxLongVersionCode="10000000000"/> android:maxLongVersionCode="10000000000"/>

View File

@@ -6,6 +6,7 @@ using Android.Content;
using Android.OS; using Android.OS;
using Android.Provider; using Android.Provider;
using Android.Views.Autofill; using Android.Views.Autofill;
using Bit.App.Resources;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Models.View; using Bit.Core.Models.View;
@@ -20,16 +21,19 @@ namespace Bit.Droid.Services
private readonly IStateService _stateService; private readonly IStateService _stateService;
private readonly IMessagingService _messagingService; private readonly IMessagingService _messagingService;
private readonly IClipboardService _clipboardService; private readonly IClipboardService _clipboardService;
private readonly IPlatformUtilsService _platformUtilsService;
private readonly LazyResolve<IEventService> _eventService; private readonly LazyResolve<IEventService> _eventService;
public AutofillHandler(IStateService stateService, public AutofillHandler(IStateService stateService,
IMessagingService messagingService, IMessagingService messagingService,
IClipboardService clipboardService, IClipboardService clipboardService,
IPlatformUtilsService platformUtilsService,
LazyResolve<IEventService> eventService) LazyResolve<IEventService> eventService)
{ {
_stateService = stateService; _stateService = stateService;
_messagingService = messagingService; _messagingService = messagingService;
_clipboardService = clipboardService; _clipboardService = clipboardService;
_platformUtilsService = platformUtilsService;
_eventService = eventService; _eventService = eventService;
} }
@@ -73,12 +77,12 @@ namespace Bit.Droid.Services
public void Autofill(CipherView cipher) public void Autofill(CipherView cipher)
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var activity = CrossCurrentActivity.Current.Activity as Xamarin.Forms.Platform.Android.FormsAppCompatActivity;
if (activity == null) if (activity == null)
{ {
return; return;
} }
if (activity.Intent?.GetBooleanExtra("autofillFramework", false) ?? false) if (activity.Intent?.GetBooleanExtra(AutofillConstants.AutofillFramework, false) ?? false)
{ {
if (cipher == null) if (cipher == null)
{ {
@@ -103,7 +107,7 @@ namespace Bit.Droid.Services
return; return;
} }
var task = CopyTotpAsync(cipher); var task = CopyTotpAsync(cipher);
var dataset = AutofillHelpers.BuildDataset(activity, parser.FieldCollection, new FilledItem(cipher)); var dataset = AutofillHelpers.BuildDataset(activity, parser.FieldCollection, new FilledItem(cipher), false);
var replyIntent = new Intent(); var replyIntent = new Intent();
replyIntent.PutExtra(AutofillManager.ExtraAuthenticationResult, dataset); replyIntent.PutExtra(AutofillManager.ExtraAuthenticationResult, dataset);
activity.SetResult(Result.Ok, replyIntent); activity.SetResult(Result.Ok, replyIntent);
@@ -202,6 +206,7 @@ namespace Bit.Droid.Services
if (totp != null) if (totp != null)
{ {
await _clipboardService.CopyTextAsync(totp); await _clipboardService.CopyTextAsync(totp);
_platformUtilsService.ShowToastForCopiedValue(AppResources.VerificationCodeTotp);
} }
} }
} }

View File

@@ -6,7 +6,6 @@ using Android.OS;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Droid.Receivers; using Bit.Droid.Receivers;
using Bit.Droid.Utilities; using Bit.Droid.Utilities;
using Plugin.CurrentActivity;
using Xamarin.Essentials; using Xamarin.Essentials;
namespace Bit.Droid.Services namespace Bit.Droid.Services
@@ -21,9 +20,9 @@ namespace Bit.Droid.Services
_stateService = stateService; _stateService = stateService;
_clearClipboardPendingIntent = new Lazy<PendingIntent>(() => _clearClipboardPendingIntent = new Lazy<PendingIntent>(() =>
PendingIntent.GetBroadcast(CrossCurrentActivity.Current.Activity, PendingIntent.GetBroadcast(Application.Context,
0, 0,
new Intent(CrossCurrentActivity.Current.Activity, typeof(ClearClipboardAlarmReceiver)), new Intent(Application.Context, typeof(ClearClipboardAlarmReceiver)),
AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.UpdateCurrent, false))); AndroidHelpers.AddPendingIntentMutabilityFlag(PendingIntentFlags.UpdateCurrent, false)));
} }
@@ -45,7 +44,7 @@ namespace Bit.Droid.Services
} }
catch (Java.Lang.SecurityException ex) when (ex.Message.Contains("does not belong to")) catch (Java.Lang.SecurityException ex) when (ex.Message.Contains("does not belong to"))
{ {
// #1962 Just ignore, the content is copied either way but there is some app interfiering in the process // #1962 Just ignore, the content is copied either way but there is some app interfering in the process
// that the OS catches and just throws this exception. // that the OS catches and just throws this exception.
} }
} }
@@ -58,9 +57,7 @@ namespace Bit.Droid.Services
private void CopyToClipboard(string text, bool isSensitive = true) private void CopyToClipboard(string text, bool isSensitive = true)
{ {
var activity = (MainActivity)CrossCurrentActivity.Current.Activity; var clipboardManager = Application.Context.GetSystemService(Context.ClipboardService) as ClipboardManager;
var clipboardManager = activity.GetSystemService(
Context.ClipboardService) as Android.Content.ClipboardManager;
var clipData = ClipData.NewPlainText("bitwarden", text); var clipData = ClipData.NewPlainText("bitwarden", text);
if (isSensitive) if (isSensitive)
{ {
@@ -87,7 +84,7 @@ namespace Bit.Droid.Services
return; return;
} }
var triggerMs = Java.Lang.JavaSystem.CurrentTimeMillis() + clearMs; var triggerMs = Java.Lang.JavaSystem.CurrentTimeMillis() + clearMs;
var alarmManager = CrossCurrentActivity.Current.Activity.GetSystemService(Context.AlarmService) as AlarmManager; var alarmManager = Application.Context.GetSystemService(Context.AlarmService) as AlarmManager;
alarmManager.Set(AlarmType.Rtc, triggerMs, _clearClipboardPendingIntent.Value); alarmManager.Set(AlarmType.Rtc, triggerMs, _clearClipboardPendingIntent.Value);
} }
} }

View File

@@ -18,6 +18,7 @@ using Bit.Core.Enums;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Bit.Droid.Utilities; using Bit.Droid.Utilities;
using Plugin.CurrentActivity; using Plugin.CurrentActivity;
using static Bit.App.Pages.SettingsPageViewModel;
namespace Bit.Droid.Services namespace Bit.Droid.Services
{ {
@@ -69,14 +70,17 @@ namespace Bit.Droid.Services
public bool LaunchApp(string appName) public bool LaunchApp(string appName)
{ {
if ((int)Build.VERSION.SdkInt < 33)
{
// API 33 required to avoid using wildcard app visibility or dangerous permissions
// https://developer.android.com/reference/android/content/pm/PackageManager#getLaunchIntentSenderForPackage(java.lang.String)
return false;
}
var activity = CrossCurrentActivity.Current.Activity; var activity = CrossCurrentActivity.Current.Activity;
appName = appName.Replace("androidapp://", string.Empty); appName = appName.Replace("androidapp://", string.Empty);
var launchIntent = activity.PackageManager.GetLaunchIntentForPackage(appName); var launchIntentSender = activity?.PackageManager?.GetLaunchIntentSenderForPackage(appName);
if (launchIntent != null) launchIntentSender?.SendIntent(activity, Result.Ok, null, null, null);
{ return launchIntentSender != null;
activity.StartActivity(launchIntent);
}
return launchIntent != null;
} }
public async Task ShowLoadingAsync(string text) public async Task ShowLoadingAsync(string text)

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Models; using Bit.App.Models;
@@ -25,13 +26,13 @@ namespace Bit.Droid.Services
try try
{ {
var fallback = ToDotnetFallbackLanguage(new PlatformCulture(netLanguage)); var fallback = ToDotnetFallbackLanguage(new PlatformCulture(netLanguage));
Console.WriteLine(netLanguage + " failed, trying " + fallback + " (" + e1.Message + ")"); Debug.WriteLine(netLanguage + " failed, trying " + fallback + " (" + e1.Message + ")");
ci = new CultureInfo(fallback); ci = new CultureInfo(fallback);
} }
catch (CultureNotFoundException e2) catch (CultureNotFoundException e2)
{ {
// iOS language not valid .NET culture, falling back to English // iOS language not valid .NET culture, falling back to English
Console.WriteLine(netLanguage + " couldn't be set, using 'en' (" + e2.Message + ")"); Debug.WriteLine(netLanguage + " couldn't be set, using 'en' (" + e2.Message + ")");
ci = new CultureInfo("en"); ci = new CultureInfo("en");
} }
} }
@@ -40,7 +41,7 @@ namespace Bit.Droid.Services
private string AndroidToDotnetLanguage(string androidLanguage) private string AndroidToDotnetLanguage(string androidLanguage)
{ {
Console.WriteLine("Android Language:" + androidLanguage); Debug.WriteLine("Android Language:" + androidLanguage);
var netLanguage = androidLanguage; var netLanguage = androidLanguage;
if (androidLanguage.StartsWith("zh")) if (androidLanguage.StartsWith("zh"))
{ {
@@ -79,13 +80,13 @@ namespace Bit.Droid.Services
// ONLY use cultures that have been tested and known to work // ONLY use cultures that have been tested and known to work
} }
} }
Console.WriteLine(".NET Language/Locale:" + netLanguage); Debug.WriteLine(".NET Language/Locale:" + netLanguage);
return netLanguage; return netLanguage;
} }
private string ToDotnetFallbackLanguage(PlatformCulture platCulture) private string ToDotnetFallbackLanguage(PlatformCulture platCulture)
{ {
Console.WriteLine(".NET Fallback Language:" + platCulture.LanguageCode); Debug.WriteLine(".NET Fallback Language:" + platCulture.LanguageCode);
var netLanguage = platCulture.LanguageCode; // use the first part of the identifier (two chars, usually); var netLanguage = platCulture.LanguageCode; // use the first part of the identifier (two chars, usually);
switch (platCulture.LanguageCode) switch (platCulture.LanguageCode)
{ {
@@ -95,7 +96,7 @@ namespace Bit.Droid.Services
// add more application-specific cases here (if required) // add more application-specific cases here (if required)
// ONLY use cultures that have been tested and known to work // ONLY use cultures that have been tested and known to work
} }
Console.WriteLine(".NET Fallback Language/Locale:" + netLanguage + " (application-specific)"); Debug.WriteLine(".NET Fallback Language/Locale:" + netLanguage + " (application-specific)");
return netLanguage; return netLanguage;
} }

View File

@@ -0,0 +1,29 @@
using System;
using System.Threading.Tasks;
using Bit.App.Services;
using Bit.Core.Abstractions;
using Bit.Core.Models;
namespace Bit.Droid.Services
{
public class WatchDeviceService : BaseWatchDeviceService
{
public WatchDeviceService(ICipherService cipherService,
IEnvironmentService environmentService,
IStateService stateService,
IVaultTimeoutService vaultTimeoutService)
: base(cipherService, environmentService, stateService, vaultTimeoutService)
{
}
protected override bool IsSupported => false;
public override bool IsConnected => false;
protected override bool CanSendData => false;
protected override Task SendDataToWatchAsync(WatchDTO watchDto) => throw new NotImplementedException();
protected override void ConnectToWatch() => throw new NotImplementedException();
}
}

View File

@@ -62,7 +62,7 @@ namespace Bit.Droid.Utilities
theme = ThemeManager.Dark; theme = ThemeManager.Dark;
} }
if (theme == ThemeManager.Dark || theme == ThemeManager.Black || theme == ThemeManager.Nord) if (theme == ThemeManager.Dark || theme == ThemeManager.Black || theme == ThemeManager.Nord || theme == ThemeManager.SolarizedDark)
{ {
LightTheme = false; LightTheme = false;
} }

View File

@@ -1,5 +1,6 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Models;
namespace Bit.App.Abstractions namespace Bit.App.Abstractions
{ {

View File

@@ -125,6 +125,9 @@
<Compile Update="Pages\Accounts\LoginPasswordlessPage.xaml.cs"> <Compile Update="Pages\Accounts\LoginPasswordlessPage.xaml.cs">
<DependentUpon>LoginPasswordlessPage.xaml</DependentUpon> <DependentUpon>LoginPasswordlessPage.xaml</DependentUpon>
</Compile> </Compile>
<Compile Update="Pages\Accounts\LoginPasswordlessRequestPage.xaml.cs">
<DependentUpon>LoginPasswordlessRequestPage.xaml</DependentUpon>
</Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -140,6 +143,7 @@
<Folder Include="Utilities\AccountManagement\" /> <Folder Include="Utilities\AccountManagement\" />
<Folder Include="Controls\DateTime\" /> <Folder Include="Controls\DateTime\" />
<Folder Include="Controls\IconLabelButton\" /> <Folder Include="Controls\IconLabelButton\" />
<Folder Include="Controls\PasswordStrengthProgressBar\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -432,5 +436,6 @@
<None Remove="Utilities\AccountManagement\" /> <None Remove="Utilities\AccountManagement\" />
<None Remove="Controls\DateTime\" /> <None Remove="Controls\DateTime\" />
<None Remove="Controls\IconLabelButton\" /> <None Remove="Controls\IconLabelButton\" />
<None Remove="Controls\PasswordStrengthProgressBar\" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -204,7 +204,7 @@ namespace Bit.App
FingerprintPhrase = loginRequestData.RequestFingerprint, FingerprintPhrase = loginRequestData.RequestFingerprint,
RequestDate = loginRequestData.CreationDate, RequestDate = loginRequestData.CreationDate,
DeviceType = loginRequestData.RequestDeviceType, DeviceType = loginRequestData.RequestDeviceType,
Origin = loginRequestData.Origin, Origin = loginRequestData.Origin
}); });
await _stateService.SetPasswordlessLoginNotificationAsync(null); await _stateService.SetPasswordlessLoginNotificationAsync(null);
_pushNotificationService.DismissLocalNotification(Constants.PasswordlessNotificationId); _pushNotificationService.DismissLocalNotification(Constants.PasswordlessNotificationId);

View File

@@ -14,7 +14,7 @@ namespace Bit.App.Controls
{ {
AccountView = accountView; AccountView = accountView;
AvatarImageSource = ServiceContainer.Resolve<IAvatarImageSourcePool>("avatarImageSourcePool") AvatarImageSource = ServiceContainer.Resolve<IAvatarImageSourcePool>("avatarImageSourcePool")
?.GetOrCreateAvatar(AccountView.UserId, AccountView.Name, AccountView.Email); ?.GetOrCreateAvatar(AccountView.UserId, AccountView.Name, AccountView.Email, AccountView.AvatarColor);
} }
public AccountView AccountView public AccountView AccountView

View File

@@ -13,6 +13,7 @@ namespace Bit.App.Controls
{ {
private readonly string _text; private readonly string _text;
private readonly string _id; private readonly string _id;
private readonly string _color;
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
@@ -23,7 +24,7 @@ namespace Bit.App.Controls
if (obj is AvatarImageSource avatar) if (obj is AvatarImageSource avatar)
{ {
return avatar._id == _id && avatar._text == _text; return avatar._id == _id && avatar._text == _text && avatar._color == _color;
} }
return base.Equals(obj); return base.Equals(obj);
@@ -31,7 +32,7 @@ namespace Bit.App.Controls
public override int GetHashCode() => _id?.GetHashCode() ?? _text?.GetHashCode() ?? -1; public override int GetHashCode() => _id?.GetHashCode() ?? _text?.GetHashCode() ?? -1;
public AvatarImageSource(string userId = null, string name = null, string email = null) public AvatarImageSource(string userId = null, string name = null, string email = null, string color = null)
{ {
_id = userId; _id = userId;
_text = name; _text = name;
@@ -39,6 +40,7 @@ namespace Bit.App.Controls
{ {
_text = email; _text = email;
} }
_color = color;
} }
public override Func<CancellationToken, Task<Stream>> Stream => GetStreamAsync; public override Func<CancellationToken, Task<Stream>> Stream => GetStreamAsync;
@@ -71,7 +73,7 @@ namespace Bit.App.Controls
chars = upperCaseText = _text.ToUpper(); chars = upperCaseText = _text.ToUpper();
} }
var bgColor = CoreHelpers.StringToColor(_id ?? upperCaseText, "#33ffffff"); var bgColor = _color ?? CoreHelpers.StringToColor(_id ?? upperCaseText, "#33ffffff");
var textColor = CoreHelpers.TextColorFromBgColor(bgColor); var textColor = CoreHelpers.TextColorFromBgColor(bgColor);
var size = 50; var size = 50;

View File

@@ -5,19 +5,19 @@ namespace Bit.App.Controls
{ {
public interface IAvatarImageSourcePool public interface IAvatarImageSourcePool
{ {
AvatarImageSource GetOrCreateAvatar(string userId, string name, string email); AvatarImageSource GetOrCreateAvatar(string userId, string name, string email, string color);
} }
public class AvatarImageSourcePool : IAvatarImageSourcePool public class AvatarImageSourcePool : IAvatarImageSourcePool
{ {
private readonly ConcurrentDictionary<string, AvatarImageSource> _cache = new ConcurrentDictionary<string, AvatarImageSource>(); private readonly ConcurrentDictionary<string, AvatarImageSource> _cache = new ConcurrentDictionary<string, AvatarImageSource>();
public AvatarImageSource GetOrCreateAvatar(string userId, string name, string email) public AvatarImageSource GetOrCreateAvatar(string userId, string name, string email, string color)
{ {
var key = $"{userId}{name}{email}"; var key = $"{userId}{name}{email}{color}";
if (!_cache.TryGetValue(key, out var avatar)) if (!_cache.TryGetValue(key, out var avatar))
{ {
avatar = new AvatarImageSource(userId, name, email); avatar = new AvatarImageSource(userId, name, email, color);
if (!_cache.TryAdd(key, avatar) if (!_cache.TryAdd(key, avatar)
&& &&
!_cache.TryGetValue(key, out avatar)) // If add fails another thread created the avatar in between the first try get and the try add. !_cache.TryGetValue(key, out avatar)) // If add fails another thread created the avatar in between the first try get and the try add.

View File

@@ -21,13 +21,13 @@ namespace Bit.App.Controls
nameof(StrokeWidth), typeof(float), typeof(CircularProgressbarView), 3f); nameof(StrokeWidth), typeof(float), typeof(CircularProgressbarView), 3f);
public static readonly BindableProperty ProgressColorProperty = BindableProperty.Create( public static readonly BindableProperty ProgressColorProperty = BindableProperty.Create(
nameof(ProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.Default); nameof(ProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.FromHex("175DDC"));
public static readonly BindableProperty EndingProgressColorProperty = BindableProperty.Create( public static readonly BindableProperty EndingProgressColorProperty = BindableProperty.Create(
nameof(EndingProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.Default); nameof(EndingProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.FromHex("dd4b39"));
public static readonly BindableProperty BackgroundProgressColorProperty = BindableProperty.Create( public static readonly BindableProperty BackgroundProgressColorProperty = BindableProperty.Create(
nameof(BackgroundProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.Default); nameof(BackgroundProgressColor), typeof(Color), typeof(CircularProgressbarView), Color.White);
public double Progress public double Progress
{ {

View File

@@ -5,7 +5,7 @@ namespace Bit.App.Controls
public class ExtendedSlider : Slider public class ExtendedSlider : Slider
{ {
public static readonly BindableProperty ThumbBorderColorProperty = BindableProperty.Create( public static readonly BindableProperty ThumbBorderColorProperty = BindableProperty.Create(
nameof(ThumbBorderColor), typeof(Color), typeof(ExtendedSlider), Color.Default); nameof(ThumbBorderColor), typeof(Color), typeof(ExtendedSlider), Color.FromHex("b5b5b5"));
public Color ThumbBorderColor public Color ThumbBorderColor
{ {

View File

@@ -5,10 +5,10 @@ namespace Bit.App.Controls
public class ExtendedStepper : Stepper public class ExtendedStepper : Stepper
{ {
public static readonly BindableProperty StepperBackgroundColorProperty = BindableProperty.Create( public static readonly BindableProperty StepperBackgroundColorProperty = BindableProperty.Create(
nameof(StepperBackgroundColor), typeof(Color), typeof(ExtendedStepper), Color.Default); nameof(StepperBackgroundColor), typeof(Color), typeof(ExtendedStepper), Color.White);
public static readonly BindableProperty StepperForegroundColorProperty = BindableProperty.Create( public static readonly BindableProperty StepperForegroundColorProperty = BindableProperty.Create(
nameof(StepperForegroundColor), typeof(Color), typeof(ExtendedStepper), Color.Default); nameof(StepperForegroundColor), typeof(Color), typeof(ExtendedStepper), Color.Black);
public Color StepperBackgroundColor public Color StepperBackgroundColor
{ {

View File

@@ -8,6 +8,7 @@
Padding="1" Padding="1"
StyleClass="btn-icon-secondary" StyleClass="btn-icon-secondary"
BackgroundColor="{Binding IconLabelBorderColor, Source={x:Reference _iconLabelButton}}" BackgroundColor="{Binding IconLabelBorderColor, Source={x:Reference _iconLabelButton}}"
BorderColor="Transparent"
HasShadow="False"> HasShadow="False">
<Frame.GestureRecognizers> <Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ButtonCommand, Source={x:Reference _iconLabelButton}}" /> <TapGestureRecognizer Command="{Binding ButtonCommand, Source={x:Reference _iconLabelButton}}" />
@@ -17,6 +18,7 @@
Padding="0" Padding="0"
CornerRadius="{Binding CornerRadius, Source={x:Reference _iconLabelButton}}" CornerRadius="{Binding CornerRadius, Source={x:Reference _iconLabelButton}}"
BackgroundColor="{Binding IconLabelBackgroundColor, Source={x:Reference _iconLabelButton}}" BackgroundColor="{Binding IconLabelBackgroundColor, Source={x:Reference _iconLabelButton}}"
BorderColor="Transparent"
IsClippedToBounds="True" IsClippedToBounds="True"
HasShadow="False"> HasShadow="False">
<StackLayout <StackLayout

View File

@@ -19,7 +19,7 @@ namespace Bit.App.Controls
nameof(Label), typeof(string), typeof(IconLabelButton)); nameof(Label), typeof(string), typeof(IconLabelButton));
public static readonly BindableProperty ButtonCommandProperty = BindableProperty.Create( public static readonly BindableProperty ButtonCommandProperty = BindableProperty.Create(
nameof(ButtonCommand), typeof(Command), typeof(IconLabelButton)); nameof(ButtonCommand), typeof(ICommand), typeof(IconLabelButton));
public static readonly BindableProperty IconLabelColorProperty = BindableProperty.Create( public static readonly BindableProperty IconLabelColorProperty = BindableProperty.Create(
nameof(IconLabelColor), typeof(Color), typeof(IconLabelButton), Color.White); nameof(IconLabelColor), typeof(Color), typeof(IconLabelButton), Color.White);

View File

@@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace Bit.App.Controls
{
public interface IPasswordStrengthable
{
string Password { get; }
List<string> UserInputs { get; }
}
}

View File

@@ -0,0 +1,17 @@
using Bit.Core.Attributes;
namespace Bit.App.Controls
{
public enum PasswordStrengthLevel
{
[LocalizableEnum("Weak")]
VeryWeak,
[LocalizableEnum("Weak")]
Weak,
[LocalizableEnum("Good")]
Good,
[LocalizableEnum("Strong")]
Strong
}
}

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" ?>
<StackLayout
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:Bit.App.Controls"
xmlns:u="clr-namespace:Bit.App.Utilities"
x:DataType="controls:PasswordStrengthViewModel"
x:Class="Bit.App.Controls.PasswordStrengthProgressBar"
StyleClass="box">
<StackLayout.Resources>
<ResourceDictionary>
<u:LocalizableEnumConverter x:Key="localizableEnum" />
</ResourceDictionary>
</StackLayout.Resources>
<ProgressBar
x:Name="_progressBar"
u:ProgressBarExtensions.AnimatedProgress="{Binding PasswordStrength}"
ScaleY="2" />
<Label
x:Name="_progressLabel"
Text="{Binding PasswordStrengthLevel, Converter={StaticResource localizableEnum}, TargetNullValue=' ' }"
StyleClass="box-footer-label" />
</StackLayout>

View File

@@ -0,0 +1,107 @@
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public partial class PasswordStrengthProgressBar : StackLayout
{
public static readonly BindableProperty PasswordStrengthLevelProperty = BindableProperty.Create(
nameof(PasswordStrengthLevel),
typeof(PasswordStrengthLevel),
typeof(PasswordStrengthProgressBar),
propertyChanged: OnControlPropertyChanged);
public static readonly BindableProperty VeryWeakColorProperty = BindableProperty.Create(
nameof(VeryWeakColor),
typeof(Color),
typeof(PasswordStrengthProgressBar),
propertyChanged: OnControlPropertyChanged);
public static readonly BindableProperty WeakColorProperty = BindableProperty.Create(
nameof(WeakColor),
typeof(Color),
typeof(PasswordStrengthProgressBar),
propertyChanged: OnControlPropertyChanged);
public static readonly BindableProperty GoodColorProperty = BindableProperty.Create(
nameof(GoodColor),
typeof(Color),
typeof(PasswordStrengthProgressBar),
propertyChanged: OnControlPropertyChanged);
public static readonly BindableProperty StrongColorProperty = BindableProperty.Create(
nameof(StrongColor),
typeof(Color),
typeof(PasswordStrengthProgressBar),
propertyChanged: OnControlPropertyChanged);
public PasswordStrengthLevel? PasswordStrengthLevel
{
get { return (PasswordStrengthLevel?)GetValue(PasswordStrengthLevelProperty); }
set { SetValue(PasswordStrengthLevelProperty, value); }
}
public Color VeryWeakColor
{
get { return (Color)GetValue(VeryWeakColorProperty); }
set { SetValue(VeryWeakColorProperty, value); }
}
public Color WeakColor
{
get { return (Color)GetValue(WeakColorProperty); }
set { SetValue(WeakColorProperty, value); }
}
public Color GoodColor
{
get { return (Color)GetValue(GoodColorProperty); }
set { SetValue(GoodColorProperty, value); }
}
public Color StrongColor
{
get { return (Color)GetValue(StrongColorProperty); }
set { SetValue(StrongColorProperty, value); }
}
public PasswordStrengthProgressBar()
{
InitializeComponent();
SetBinding(PasswordStrengthProgressBar.PasswordStrengthLevelProperty, new Binding() { Path = nameof(PasswordStrengthViewModel.PasswordStrengthLevel) });
}
private static void OnControlPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
(bindable as PasswordStrengthProgressBar)?.UpdateColors();
}
public void UpdateColors()
{
if (_progressBar == null || _progressLabel == null)
{
return;
}
_progressBar.ProgressColor = GetColorForStrength();
_progressLabel.TextColor = _progressBar.ProgressColor;
}
private Color GetColorForStrength()
{
switch (PasswordStrengthLevel)
{
case Controls.PasswordStrengthLevel.VeryWeak:
return VeryWeakColor;
case Controls.PasswordStrengthLevel.Weak:
return WeakColor;
case Controls.PasswordStrengthLevel.Good:
return GoodColor;
case Controls.PasswordStrengthLevel.Strong:
return StrongColor;
default:
return Color.Transparent;
}
}
}
}

View File

@@ -0,0 +1,67 @@
using System.Collections.Generic;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class PasswordStrengthViewModel : ExtendedViewModel
{
private readonly IPasswordGenerationService _passwordGenerationService;
private readonly IPasswordStrengthable _passwordStrengthable;
private double _passwordStrength;
private Color _passwordColor;
private PasswordStrengthLevel? _passwordStrengthLevel;
public PasswordStrengthViewModel(IPasswordStrengthable passwordStrengthable)
{
_passwordGenerationService = ServiceContainer.Resolve<IPasswordGenerationService>();
_passwordStrengthable = passwordStrengthable;
}
public double PasswordStrength
{
get => _passwordStrength;
set => SetProperty(ref _passwordStrength, value);
}
public PasswordStrengthLevel? PasswordStrengthLevel
{
get => _passwordStrengthLevel;
set => SetProperty(ref _passwordStrengthLevel, value);
}
public List<string> GetPasswordStrengthUserInput(string email) => _passwordGenerationService.GetPasswordStrengthUserInput(email);
public void CalculatePasswordStrength()
{
if (string.IsNullOrEmpty(_passwordStrengthable.Password))
{
PasswordStrength = 0;
PasswordStrengthLevel = null;
return;
}
var passwordStrength = _passwordGenerationService.PasswordStrength(_passwordStrengthable.Password, _passwordStrengthable.UserInputs);
// The passwordStrength.Score is 0..4, convertion was made to be used as a progress directly by the control 0..1
PasswordStrength = (passwordStrength.Score + 1f) / 5f;
if (PasswordStrength <= 0.4f)
{
PasswordStrengthLevel = Controls.PasswordStrengthLevel.VeryWeak;
}
else if (PasswordStrength <= 0.6f)
{
PasswordStrengthLevel = Controls.PasswordStrengthLevel.Weak;
}
else if (PasswordStrength <= 0.8f)
{
PasswordStrengthLevel = Controls.PasswordStrengthLevel.Good;
}
else
{
PasswordStrengthLevel = Controls.PasswordStrengthLevel.Strong;
}
}
}
}

View File

@@ -4,6 +4,8 @@ using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Resources; using Bit.App.Resources;
using Bit.App.Utilities;
using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Models.Domain; using Bit.Core.Models.Domain;
using Bit.Core.Utilities; using Bit.Core.Utilities;
@@ -147,8 +149,8 @@ namespace Bit.App.Pages
} }
if (IsPolicyInEffect) if (IsPolicyInEffect)
{ {
var userInput = await GetPasswordStrengthUserInput(); var userInputs = _passwordGenerationService.GetPasswordStrengthUserInput(await _stateService.GetEmailAsync());
var passwordStrength = _passwordGenerationService.PasswordStrength(MasterPassword, userInput); var passwordStrength = _passwordGenerationService.PasswordStrength(MasterPassword, userInputs);
if (!await _policyService.EvaluateMasterPassword(passwordStrength.Score, MasterPassword, Policy)) if (!await _policyService.EvaluateMasterPassword(passwordStrength.Score, MasterPassword, Policy))
{ {
await _platformUtilsService.ShowDialogAsync(AppResources.MasterPasswordPolicyValidationMessage, await _platformUtilsService.ShowDialogAsync(AppResources.MasterPasswordPolicyValidationMessage,
@@ -158,7 +160,7 @@ namespace Bit.App.Pages
} }
else else
{ {
if (MasterPassword.Length < 8) if (MasterPassword.Length < Constants.MasterPasswordMinimumChars)
{ {
await _platformUtilsService.ShowDialogAsync(AppResources.MasterPasswordLengthValMessage, await _platformUtilsService.ShowDialogAsync(AppResources.MasterPasswordLengthValMessage,
AppResources.MasterPasswordPolicyValidationTitle, AppResources.Ok); AppResources.MasterPasswordPolicyValidationTitle, AppResources.Ok);
@@ -174,19 +176,5 @@ namespace Bit.App.Pages
return true; return true;
} }
private async Task<List<string>> GetPasswordStrengthUserInput()
{
var email = await _stateService.GetEmailAsync();
List<string> userInput = null;
var atPosition = email.IndexOf('@');
if (atPosition > -1)
{
var rx = new Regex("/[^A-Za-z0-9]/", RegexOptions.Compiled);
var data = rx.Split(email.Substring(0, atPosition).Trim().ToLower());
userInput = new List<string>(data);
}
return userInput;
}
} }
} }

View File

@@ -51,7 +51,9 @@
x:Name="_email" x:Name="_email"
Text="{Binding Email}" Text="{Binding Email}"
Keyboard="Email" Keyboard="Email"
StyleClass="box-value"> StyleClass="box-value"
ReturnType="Go"
ReturnCommand="{Binding ContinueCommand}">
<VisualStateManager.VisualStateGroups> <VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates"> <VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled"> <VisualState x:Name="Disabled">

View File

@@ -28,6 +28,7 @@ namespace Bit.App.Pages
private readonly IBiometricService _biometricService; private readonly IBiometricService _biometricService;
private readonly IKeyConnectorService _keyConnectorService; private readonly IKeyConnectorService _keyConnectorService;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IWatchDeviceService _watchDeviceService;
private readonly WeakEventManager<int?> _secretEntryFocusWeakEventManager = new WeakEventManager<int?>(); private readonly WeakEventManager<int?> _secretEntryFocusWeakEventManager = new WeakEventManager<int?>();
private string _email; private string _email;
@@ -56,6 +57,7 @@ namespace Bit.App.Pages
_biometricService = ServiceContainer.Resolve<IBiometricService>("biometricService"); _biometricService = ServiceContainer.Resolve<IBiometricService>("biometricService");
_keyConnectorService = ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService"); _keyConnectorService = ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService");
_logger = ServiceContainer.Resolve<ILogger>("logger"); _logger = ServiceContainer.Resolve<ILogger>("logger");
_watchDeviceService = ServiceContainer.Resolve<IWatchDeviceService>();
PageTitle = AppResources.VerifyMasterPassword; PageTitle = AppResources.VerifyMasterPassword;
TogglePasswordCommand = new Command(TogglePassword); TogglePasswordCommand = new Command(TogglePassword);
@@ -387,6 +389,7 @@ namespace Bit.App.Pages
private async Task DoContinueAsync() private async Task DoContinueAsync()
{ {
await _stateService.SetBiometricLockedAsync(false); await _stateService.SetBiometricLockedAsync(false);
_watchDeviceService.SyncDataToWatchAsync().FireAndForget();
_messagingService.Send("unlocked"); _messagingService.Send("unlocked");
UnlockedAction?.Invoke(); UnlockedAction?.Invoke();
} }

View File

@@ -110,8 +110,8 @@
VerticalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"
Icon="{Binding Source={x:Static core:BitwardenIcons.Device}}" Icon="{Binding Source={x:Static core:BitwardenIcons.Device}}"
Label="{u:I18n LogInWithAnotherDevice}" Label="{u:I18n LogInWithAnotherDevice}"
ButtonCommand="{Binding LogInCommand}" ButtonCommand="{Binding LogInWithDeviceCommand}"
IsVisible="False"/> IsVisible="{Binding IsKnownDevice}"/>
<controls:IconLabelButton <controls:IconLabelButton
HorizontalOptions="Fill" HorizontalOptions="Fill"
VerticalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"

View File

@@ -27,9 +27,9 @@ namespace Bit.App.Pages
_vm.Page = this; _vm.Page = this;
_vm.StartTwoFactorAction = () => Device.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync()); _vm.StartTwoFactorAction = () => Device.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync());
_vm.LogInSuccessAction = () => Device.BeginInvokeOnMainThread(async () => await LogInSuccessAsync()); _vm.LogInSuccessAction = () => Device.BeginInvokeOnMainThread(async () => await LogInSuccessAsync());
_vm.LogInWithDeviceAction = () => StartLoginWithDeviceAsync().FireAndForget();
_vm.StartSsoLoginAction = () => Device.BeginInvokeOnMainThread(async () => await StartSsoLoginAsync()); _vm.StartSsoLoginAction = () => Device.BeginInvokeOnMainThread(async () => await StartSsoLoginAsync());
_vm.UpdateTempPasswordAction = _vm.UpdateTempPasswordAction = () => Device.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync());
() => Device.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync());
_vm.CloseAction = async () => _vm.CloseAction = async () =>
{ {
await _accountListOverlay.HideAsync(); await _accountListOverlay.HideAsync();
@@ -122,6 +122,12 @@ namespace Bit.App.Pages
} }
} }
private async Task StartLoginWithDeviceAsync()
{
var page = new LoginPasswordlessRequestPage(_vm.Email, _appOptions);
await Navigation.PushModalAsync(new NavigationPage(page));
}
private async Task StartSsoLoginAsync() private async Task StartSsoLoginAsync()
{ {
var page = new LoginSsoPage(_appOptions); var page = new LoginSsoPage(_appOptions);

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
@@ -59,6 +60,7 @@ namespace Bit.App.Pages
TogglePasswordCommand = new Command(TogglePassword); TogglePasswordCommand = new Command(TogglePassword);
LogInCommand = new Command(async () => await LogInAsync()); LogInCommand = new Command(async () => await LogInAsync());
MoreCommand = new AsyncCommand(MoreAsync, onException: _logger.Exception, allowsMultipleExecutions: false); MoreCommand = new AsyncCommand(MoreAsync, onException: _logger.Exception, allowsMultipleExecutions: false);
LogInWithDeviceCommand = new AsyncCommand(() => Device.InvokeOnMainThreadAsync(LogInWithDeviceAction), onException: _logger.Exception, allowsMultipleExecutions: false);
AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger) AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger)
{ {
@@ -116,6 +118,7 @@ namespace Bit.App.Pages
public Command LogInCommand { get; } public Command LogInCommand { get; }
public Command TogglePasswordCommand { get; } public Command TogglePasswordCommand { get; }
public ICommand MoreCommand { get; internal set; } public ICommand MoreCommand { get; internal set; }
public ICommand LogInWithDeviceCommand { get; }
public string ShowPasswordIcon => ShowPassword ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye; public string ShowPasswordIcon => ShowPassword ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
public string PasswordVisibilityAccessibilityText => ShowPassword ? AppResources.PasswordIsVisibleTapToHide : AppResources.PasswordIsNotVisibleTapToShow; public string PasswordVisibilityAccessibilityText => ShowPassword ? AppResources.PasswordIsVisibleTapToHide : AppResources.PasswordIsNotVisibleTapToShow;
public string LoggingInAsText => string.Format(AppResources.LoggingInAsX, Email); public string LoggingInAsText => string.Format(AppResources.LoggingInAsX, Email);
@@ -123,6 +126,7 @@ namespace Bit.App.Pages
public bool CanRemoveAccount { get; set; } public bool CanRemoveAccount { get; set; }
public Action StartTwoFactorAction { get; set; } public Action StartTwoFactorAction { get; set; }
public Action LogInSuccessAction { get; set; } public Action LogInSuccessAction { get; set; }
public Action LogInWithDeviceAction { get; set; }
public Action UpdateTempPasswordAction { get; set; } public Action UpdateTempPasswordAction { get; set; }
public Action StartSsoLoginAction { get; set; } public Action StartSsoLoginAction { get; set; }
public Action CloseAction { get; set; } public Action CloseAction { get; set; }
@@ -301,15 +305,5 @@ namespace Bit.App.Pages
_logger.Exception(e); _logger.Exception(e);
} }
} }
private void HandleException(Exception ex)
{
Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
{
await _deviceActionService.HideLoadingAsync();
await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage);
}).FireAndForget();
_logger.Exception(ex);
}
} }
} }

View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" ?>
<pages:BaseContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Bit.App.Pages.LoginPasswordlessRequestPage"
xmlns:pages="clr-namespace:Bit.App.Pages"
xmlns:controls="clr-namespace:Bit.App.Controls"
xmlns:u="clr-namespace:Bit.App.Utilities"
x:DataType="pages:LoginPasswordlessRequestViewModel"
Title="{Binding PageTitle}">
<ContentPage.BindingContext>
<pages:LoginPasswordlessRequestViewModel />
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Text="{u:I18n Close}" Command="{Binding CloseCommand}" Order="Primary" Priority="-1" x:Name="_closeItem"/>
</ContentPage.ToolbarItems>
<ScrollView>
<StackLayout
Padding="7, 0, 7, 20">
<Label
Text="{u:I18n LogInInitiated}"
FontSize="Title"
FontAttributes="Bold"
Margin="0,14,0,21"/>
<Label
Text="{u:I18n ANotificationHasBeenSentToYourDevice}"
FontSize="Small"
Margin="0,0,0,10"/>
<Label
Text="{u:I18n PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice}"
FontSize="Small"
Margin="0,0,0,24"/>
<Label
Text="{u:I18n FingerprintPhrase}"
FontSize="Small"
FontAttributes="Bold"/>
<controls:MonoLabel
FormattedText="{Binding FingerprintPhrase}"
FontSize="Medium"
TextColor="{DynamicResource FingerprintPhrase}"/>
<Label
Text="{u:I18n ResendNotification}"
StyleClass="text-md"
HorizontalOptions="Start"
Margin="0,40,0,0"
TextColor="{DynamicResource HyperlinkColor}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding CreatePasswordlessLoginCommand}" />
</Label.GestureRecognizers>
</Label>
<StackLayout
Orientation="Horizontal"
Margin="0,30,0,0">
<Label
Text="{u:I18n NeedAnotherOption}"
FontSize="Small"
VerticalTextAlignment="End"/>
<Label
Text="{u:I18n ViewAllLoginOptions}"
StyleClass="text-md"
VerticalTextAlignment="End"
VerticalOptions="CenterAndExpand"
Margin="5, 0"
TextColor="{DynamicResource HyperlinkColor}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding CloseCommand}" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
</StackLayout>
</ScrollView>
</pages:BaseContentPage>

View File

@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Bit.App.Models;
using Bit.App.Utilities;
using Xamarin.Forms;
namespace Bit.App.Pages
{
public partial class LoginPasswordlessRequestPage : BaseContentPage
{
private LoginPasswordlessRequestViewModel _vm;
private readonly AppOptions _appOptions;
public LoginPasswordlessRequestPage(string email, AppOptions appOptions = null)
{
InitializeComponent();
_appOptions = appOptions;
_vm = BindingContext as LoginPasswordlessRequestViewModel;
_vm.Page = this;
_vm.Email = email;
_vm.StartTwoFactorAction = () => Device.BeginInvokeOnMainThread(async () => await StartTwoFactorAsync());
_vm.LogInSuccessAction = () => Device.BeginInvokeOnMainThread(async () => await LogInSuccessAsync());
_vm.UpdateTempPasswordAction = () => Device.BeginInvokeOnMainThread(async () => await UpdateTempPasswordAsync());
_vm.CloseAction = () => { Navigation.PopModalAsync(); };
_vm.CreatePasswordlessLoginCommand.Execute(null);
}
protected override void OnAppearing()
{
base.OnAppearing();
_vm.StartCheckLoginRequestStatus();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
_vm.StopCheckLoginRequestStatus();
}
private async Task StartTwoFactorAsync()
{
var page = new TwoFactorPage(false, _appOptions);
await Navigation.PushModalAsync(new NavigationPage(page));
}
private async Task LogInSuccessAsync()
{
if (AppHelpers.SetAlternateMainPage(_appOptions))
{
return;
}
var previousPage = await AppHelpers.ClearPreviousPage();
Application.Current.MainPage = new TabsPage(_appOptions, previousPage);
}
private async Task UpdateTempPasswordAsync()
{
var page = new UpdateTempPasswordPage();
await Navigation.PushModalAsync(new NavigationPage(page));
}
}
}

View File

@@ -0,0 +1,194 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using Bit.App.Abstractions;
using Bit.App.Resources;
using Bit.App.Utilities;
using Bit.Core;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Models.Domain;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace Bit.App.Pages
{
public class LoginPasswordlessRequestViewModel : CaptchaProtectedViewModel
{
private const int REQUEST_TIME_UPDATE_PERIOD_IN_SECONDS = 4;
private IDeviceActionService _deviceActionService;
private IAuthService _authService;
private ISyncService _syncService;
private II18nService _i18nService;
private IStateService _stateService;
private IPlatformUtilsService _platformUtilsService;
private IEnvironmentService _environmentService;
private ILogger _logger;
protected override II18nService i18nService => _i18nService;
protected override IEnvironmentService environmentService => _environmentService;
protected override IDeviceActionService deviceActionService => _deviceActionService;
protected override IPlatformUtilsService platformUtilsService => _platformUtilsService;
private CancellationTokenSource _checkLoginRequestStatusCts;
private Task _checkLoginRequestStatusTask;
private string _fingerprintPhrase;
private string _email;
private string _requestId;
private string _requestAccessCode;
// Item1 publicKey, Item2 privateKey
private Tuple<byte[], byte[]> _requestKeyPair;
public LoginPasswordlessRequestViewModel()
{
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>();
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>();
_environmentService = ServiceContainer.Resolve<IEnvironmentService>();
_authService = ServiceContainer.Resolve<IAuthService>();
_syncService = ServiceContainer.Resolve<ISyncService>();
_i18nService = ServiceContainer.Resolve<II18nService>();
_stateService = ServiceContainer.Resolve<IStateService>();
_logger = ServiceContainer.Resolve<ILogger>();
PageTitle = AppResources.LogInWithAnotherDevice;
CreatePasswordlessLoginCommand = new AsyncCommand(CreatePasswordlessLoginAsync,
onException: ex => HandleException(ex),
allowsMultipleExecutions: false);
CloseCommand = new AsyncCommand(() => Device.InvokeOnMainThreadAsync(CloseAction),
onException: _logger.Exception,
allowsMultipleExecutions: false);
}
public Action StartTwoFactorAction { get; set; }
public Action LogInSuccessAction { get; set; }
public Action UpdateTempPasswordAction { get; set; }
public Action CloseAction { get; set; }
public ICommand CreatePasswordlessLoginCommand { get; }
public ICommand CloseCommand { get; }
public string FingerprintPhrase
{
get => _fingerprintPhrase;
set => SetProperty(ref _fingerprintPhrase, value);
}
public string Email
{
get => _email;
set => SetProperty(ref _email, value);
}
public void StartCheckLoginRequestStatus()
{
try
{
_checkLoginRequestStatusCts?.Cancel();
_checkLoginRequestStatusCts = new CancellationTokenSource();
_checkLoginRequestStatusTask = new TimerTask(_logger, CheckLoginRequestStatus, _checkLoginRequestStatusCts).RunPeriodic(TimeSpan.FromSeconds(REQUEST_TIME_UPDATE_PERIOD_IN_SECONDS));
}
catch (Exception ex)
{
_logger.Exception(ex);
}
}
public void StopCheckLoginRequestStatus()
{
try
{
_checkLoginRequestStatusCts?.Cancel();
_checkLoginRequestStatusCts?.Dispose();
_checkLoginRequestStatusCts = null;
}
catch (Exception ex)
{
_logger.Exception(ex);
}
}
private async Task CheckLoginRequestStatus()
{
if (string.IsNullOrEmpty(_requestId) || string.IsNullOrEmpty(_requestAccessCode))
{
return;
}
try
{
var response = await _authService.GetPasswordlessLoginResponseAsync(_requestId, _requestAccessCode);
if (response.RequestApproved == null || !response.RequestApproved.Value)
{
return;
}
StopCheckLoginRequestStatus();
var authResult = await _authService.LogInPasswordlessAsync(Email, _requestAccessCode, _requestId, _requestKeyPair.Item2, response.Key, response.MasterPasswordHash);
await AppHelpers.ResetInvalidUnlockAttemptsAsync();
if (await HandleCaptchaAsync(authResult.CaptchaSiteKey, authResult.CaptchaNeeded, CheckLoginRequestStatus))
{
return;
}
if (authResult.TwoFactor)
{
StartTwoFactorAction?.Invoke();
}
else if (authResult.ForcePasswordReset)
{
UpdateTempPasswordAction?.Invoke();
}
else
{
_syncService.FullSyncAsync(true).FireAndForget();
LogInSuccessAction?.Invoke();
}
}
catch (Exception ex)
{
StartCheckLoginRequestStatus();
HandleException(ex);
}
}
private async Task CreatePasswordlessLoginAsync()
{
await Device.InvokeOnMainThreadAsync(() => _deviceActionService.ShowLoadingAsync(AppResources.Loading));
var response = await _authService.PasswordlessCreateLoginRequestAsync(_email);
if (response != null)
{
FingerprintPhrase = response.RequestFingerprint;
_requestId = response.Id;
_requestAccessCode = response.RequestAccessCode;
_requestKeyPair = response.RequestKeyPair;
}
await _deviceActionService.HideLoadingAsync();
}
private void HandleException(Exception ex)
{
Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
{
await _deviceActionService.HideLoadingAsync();
await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage);
}).FireAndForget();
_logger.Exception(ex);
}
}
}

View File

@@ -117,6 +117,14 @@ namespace Bit.App.Pages
return; return;
} }
var loginRequestData = await _authService.GetPasswordlessLoginRequestByIdAsync(LoginRequest.Id);
if (loginRequestData.RequestApproved.HasValue && loginRequestData.ResponseDate.HasValue)
{
await _platformUtilsService.ShowDialogAsync(AppResources.ThisRequestIsNoLongerValid);
await Page.Navigation.PopModalAsync();
return;
}
await _deviceActionService.ShowLoadingAsync(AppResources.Loading); await _deviceActionService.ShowLoadingAsync(AppResources.Loading);
await _authService.PasswordlessLoginAsync(LoginRequest.Id, LoginRequest.PubKey, approveRequest); await _authService.PasswordlessLoginAsync(LoginRequest.Id, LoginRequest.PubKey, approveRequest);
await _deviceActionService.HideLoadingAsync(); await _deviceActionService.HideLoadingAsync();
@@ -140,16 +148,6 @@ namespace Bit.App.Pages
return string.Format(AppResources.XMinutesAgo, DateTime.UtcNow.Minute - requestDate.Value.ToUniversalTime().Minute); return string.Format(AppResources.XMinutesAgo, DateTime.UtcNow.Minute - requestDate.Value.ToUniversalTime().Minute);
} }
private void HandleException(Exception ex)
{
Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
{
await _deviceActionService.HideLoadingAsync();
await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage);
}).FireAndForget();
_logger.Exception(ex);
}
} }
public class LoginPasswordlessDetails public class LoginPasswordlessDetails

View File

@@ -25,7 +25,7 @@
</ContentPage.ToolbarItems> </ContentPage.ToolbarItems>
<ScrollView> <ScrollView>
<StackLayout Spacing="20"> <StackLayout Spacing="10">
<StackLayout StyleClass="box"> <StackLayout StyleClass="box">
<StackLayout StyleClass="box-row"> <StackLayout StyleClass="box-row">
<Label <Label
@@ -72,8 +72,19 @@
AutomationProperties.HelpText="{Binding PasswordVisibilityAccessibilityText}"/> AutomationProperties.HelpText="{Binding PasswordVisibilityAccessibilityText}"/>
</Grid> </Grid>
<Label <Label
Text="{u:I18n MasterPasswordDescription}" StyleClass="box-sub-label"
StyleClass="box-footer-label" /> Margin="0,0,0,10">
<Label.FormattedText>
<FormattedString>
<Span Text="{u:I18n Important}" TextColor="{DynamicResource InfoColor}"/>
<Span Text=": " TextColor="{DynamicResource InfoColor}"/>
<Span Text="{Binding MasterPasswordMininumCharactersDescription}" TextColor="{DynamicResource MutedColor}"/>
</FormattedString>
</Label.FormattedText>
</Label>
<controls:PasswordStrengthProgressBar
BindingContext="{Binding PasswordStrengthViewModel}"
Margin="0,0"/>
</StackLayout> </StackLayout>
<StackLayout StyleClass="box"> <StackLayout StyleClass="box">
<Grid StyleClass="box-row"> <Grid StyleClass="box-row">
@@ -126,6 +137,17 @@
StyleClass="box-footer-label" /> StyleClass="box-footer-label" />
</StackLayout> </StackLayout>
<StackLayout StyleClass="box"> <StackLayout StyleClass="box">
<StackLayout StyleClass="box-row, box-row-switch">
<Switch
IsToggled="{Binding CheckExposedMasterPassword}"
StyleClass="box-value"
HorizontalOptions="Start"
Margin="0, 0, 10, 0"/>
<Label
Text="{u:I18n CheckKnownDataBreachesForThisPassword}"
StyleClass="box-footer-label"
VerticalOptions="Center"/>
</StackLayout>
<StackLayout StyleClass="box-row, box-row-switch" <StackLayout StyleClass="box-row, box-row-switch"
IsVisible="{Binding ShowTerms}"> IsVisible="{Binding ShowTerms}">
<Switch <Switch

View File

@@ -1,28 +1,36 @@
using System; using System;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Controls;
using Bit.App.Resources; using Bit.App.Resources;
using Bit.App.Utilities;
using Bit.Core; using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Exceptions; using Bit.Core.Exceptions;
using Bit.Core.Models.Request; using Bit.Core.Models.Request;
using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Xamarin.Forms; using Xamarin.Forms;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
public class RegisterPageViewModel : CaptchaProtectedViewModel public class RegisterPageViewModel : CaptchaProtectedViewModel, IPasswordStrengthable
{ {
private readonly IDeviceActionService _deviceActionService; private readonly IDeviceActionService _deviceActionService;
private readonly II18nService _i18nService; private readonly II18nService _i18nService;
private readonly IEnvironmentService _environmentService; private readonly IEnvironmentService _environmentService;
private readonly IAuditService _auditService;
private readonly IApiService _apiService; private readonly IApiService _apiService;
private readonly ICryptoService _cryptoService; private readonly ICryptoService _cryptoService;
private readonly IPlatformUtilsService _platformUtilsService; private readonly IPlatformUtilsService _platformUtilsService;
private string _email;
private string _masterPassword;
private bool _showPassword; private bool _showPassword;
private bool _acceptPolicies; private bool _acceptPolicies;
private bool _checkExposedMasterPassword;
public RegisterPageViewModel() public RegisterPageViewModel()
{ {
@@ -32,12 +40,14 @@ namespace Bit.App.Pages
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService"); _platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
_i18nService = ServiceContainer.Resolve<II18nService>("i18nService"); _i18nService = ServiceContainer.Resolve<II18nService>("i18nService");
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService"); _environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
_auditService = ServiceContainer.Resolve<IAuditService>();
PageTitle = AppResources.CreateAccount; PageTitle = AppResources.CreateAccount;
TogglePasswordCommand = new Command(TogglePassword); TogglePasswordCommand = new Command(TogglePassword);
ToggleConfirmPasswordCommand = new Command(ToggleConfirmPassword); ToggleConfirmPasswordCommand = new Command(ToggleConfirmPassword);
SubmitCommand = new Command(async () => await SubmitAsync()); SubmitCommand = new Command(async () => await SubmitAsync());
ShowTerms = !_platformUtilsService.IsSelfHost(); ShowTerms = !_platformUtilsService.IsSelfHost();
PasswordStrengthViewModel = new PasswordStrengthViewModel(this);
} }
public ICommand PoliciesClickCommand => new Command<string>((url) => public ICommand PoliciesClickCommand => new Command<string>((url) =>
@@ -61,6 +71,34 @@ namespace Bit.App.Pages
get => _acceptPolicies; get => _acceptPolicies;
set => SetProperty(ref _acceptPolicies, value); set => SetProperty(ref _acceptPolicies, value);
} }
public bool CheckExposedMasterPassword
{
get => _checkExposedMasterPassword;
set => SetProperty(ref _checkExposedMasterPassword, value);
}
public string MasterPassword
{
get => _masterPassword;
set
{
SetProperty(ref _masterPassword, value);
PasswordStrengthViewModel.CalculatePasswordStrength();
}
}
public string Email
{
get => _email;
set => SetProperty(ref _email, value);
}
public string Password => MasterPassword;
public List<string> UserInputs => PasswordStrengthViewModel.GetPasswordStrengthUserInput(Email);
public string MasterPasswordMininumCharactersDescription => string.Format(AppResources.YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum,
Constants.MasterPasswordMinimumChars);
public PasswordStrengthViewModel PasswordStrengthViewModel { get; }
public bool ShowTerms { get; set; } public bool ShowTerms { get; set; }
public Command SubmitCommand { get; } public Command SubmitCommand { get; }
public Command TogglePasswordCommand { get; } public Command TogglePasswordCommand { get; }
@@ -68,13 +106,10 @@ namespace Bit.App.Pages
public string ShowPasswordIcon => ShowPassword ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye; public string ShowPasswordIcon => ShowPassword ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
public string PasswordVisibilityAccessibilityText => ShowPassword ? AppResources.PasswordIsVisibleTapToHide : AppResources.PasswordIsNotVisibleTapToShow; public string PasswordVisibilityAccessibilityText => ShowPassword ? AppResources.PasswordIsVisibleTapToHide : AppResources.PasswordIsNotVisibleTapToShow;
public string Name { get; set; } public string Name { get; set; }
public string Email { get; set; }
public string MasterPassword { get; set; }
public string ConfirmMasterPassword { get; set; } public string ConfirmMasterPassword { get; set; }
public string Hint { get; set; } public string Hint { get; set; }
public Action RegistrationSuccess { get; set; } public Action RegistrationSuccess { get; set; }
public Action CloseAction { get; set; } public Action CloseAction { get; set; }
protected override II18nService i18nService => _i18nService; protected override II18nService i18nService => _i18nService;
protected override IEnvironmentService environmentService => _environmentService; protected override IEnvironmentService environmentService => _environmentService;
protected override IDeviceActionService deviceActionService => _deviceActionService; protected override IDeviceActionService deviceActionService => _deviceActionService;
@@ -110,7 +145,7 @@ namespace Bit.App.Pages
AppResources.Ok); AppResources.Ok);
return; return;
} }
if (MasterPassword.Length < 8) if (MasterPassword.Length < Constants.MasterPasswordMinimumChars)
{ {
await _platformUtilsService.ShowDialogAsync(AppResources.MasterPasswordLengthValMessage, await _platformUtilsService.ShowDialogAsync(AppResources.MasterPasswordLengthValMessage,
AppResources.AnErrorHasOccurred, AppResources.Ok); AppResources.AnErrorHasOccurred, AppResources.Ok);
@@ -128,8 +163,10 @@ namespace Bit.App.Pages
AppResources.AnErrorHasOccurred, AppResources.Ok); AppResources.AnErrorHasOccurred, AppResources.Ok);
return; return;
} }
if (await IsPasswordWeakOrExposed())
// TODO: Password strength check? {
return;
}
if (showLoading) if (showLoading)
{ {
@@ -139,8 +176,7 @@ namespace Bit.App.Pages
Name = string.IsNullOrWhiteSpace(Name) ? null : Name; Name = string.IsNullOrWhiteSpace(Name) ? null : Name;
Email = Email.Trim().ToLower(); Email = Email.Trim().ToLower();
var kdf = KdfType.PBKDF2_SHA256; var kdf = KdfType.PBKDF2_SHA256;
var kdfIterations = 100_000; var key = await _cryptoService.MakeKeyAsync(MasterPassword, Email, kdf, Constants.KdfIterations);
var key = await _cryptoService.MakeKeyAsync(MasterPassword, Email, kdf, kdfIterations);
var encKey = await _cryptoService.MakeEncKeyAsync(key); var encKey = await _cryptoService.MakeEncKeyAsync(key);
var hashedPassword = await _cryptoService.HashPasswordAsync(MasterPassword, key); var hashedPassword = await _cryptoService.HashPasswordAsync(MasterPassword, key);
var keys = await _cryptoService.MakeKeyPairAsync(encKey.Item1); var keys = await _cryptoService.MakeKeyPairAsync(encKey.Item1);
@@ -152,7 +188,7 @@ namespace Bit.App.Pages
MasterPasswordHint = Hint, MasterPasswordHint = Hint,
Key = encKey.Item2.EncryptedString, Key = encKey.Item2.EncryptedString,
Kdf = kdf, Kdf = kdf,
KdfIterations = kdfIterations, KdfIterations = Constants.KdfIterations,
Keys = new KeysRequest Keys = new KeysRequest
{ {
PublicKey = keys.Item1, PublicKey = keys.Item1,
@@ -160,6 +196,7 @@ namespace Bit.App.Pages
}, },
CaptchaResponse = _captchaToken, CaptchaResponse = _captchaToken,
}; };
// TODO: org invite? // TODO: org invite?
try try
@@ -208,5 +245,43 @@ namespace Bit.App.Pages
entry.Focus(); entry.Focus();
entry.CursorPosition = String.IsNullOrEmpty(ConfirmMasterPassword) ? 0 : ConfirmMasterPassword.Length; entry.CursorPosition = String.IsNullOrEmpty(ConfirmMasterPassword) ? 0 : ConfirmMasterPassword.Length;
} }
private async Task<bool> IsPasswordWeakOrExposed()
{
try
{
var title = string.Empty;
var message = string.Empty;
var exposedPassword = CheckExposedMasterPassword ? await _auditService.PasswordLeakedAsync(MasterPassword) > 0 : false;
var weakPassword = PasswordStrengthViewModel.PasswordStrengthLevel <= PasswordStrengthLevel.Weak;
if (exposedPassword && weakPassword)
{
title = AppResources.WeakAndExposedMasterPassword;
message = AppResources.WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription;
}
else if (exposedPassword)
{
title = AppResources.ExposedMasterPassword;
message = AppResources.PasswordFoundInADataBreachAlertDescription;
}
else if (weakPassword)
{
title = AppResources.WeakMasterPassword;
message = AppResources.WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount;
}
if (exposedPassword || weakPassword)
{
return !await _platformUtilsService.ShowDialogAsync(message, title, AppResources.Yes, AppResources.No);
}
}
catch (Exception ex)
{
HandleException(ex);
}
return false;
}
} }
} }

View File

@@ -47,7 +47,7 @@
Margin="0, 12, 0, 0" Margin="0, 12, 0, 0"
HasShadow="False" HasShadow="False"
BackgroundColor="Transparent" BackgroundColor="Transparent"
BorderColor="Accent"> BorderColor="{DynamicResource PrimaryColor}">
<Label <Label
Text="{u:I18n ResetPasswordAutoEnrollInviteWarning}" Text="{u:I18n ResetPasswordAutoEnrollInviteWarning}"
StyleClass="text-muted, text-sm, text-bold" StyleClass="text-muted, text-sm, text-bold"
@@ -69,7 +69,7 @@
Margin="0, 12, 0, 0" Margin="0, 12, 0, 0"
HasShadow="False" HasShadow="False"
BackgroundColor="Transparent" BackgroundColor="Transparent"
BorderColor="Accent"> BorderColor="{DynamicResource PrimaryColor}">
<Label <Label
Text="{Binding PolicySummary}" Text="{Binding PolicySummary}"
StyleClass="text-muted, text-sm, text-bold" StyleClass="text-muted, text-sm, text-bold"

View File

@@ -5,6 +5,7 @@ using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Bit.App.Abstractions; using Bit.App.Abstractions;
using Bit.App.Resources; using Bit.App.Resources;
using Bit.App.Utilities;
using Bit.Core; using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
@@ -137,8 +138,8 @@ namespace Bit.App.Pages
} }
if (IsPolicyInEffect) if (IsPolicyInEffect)
{ {
var userInput = await GetPasswordStrengthUserInput(); var userInputs = _passwordGenerationService.GetPasswordStrengthUserInput(await _stateService.GetEmailAsync());
var passwordStrength = _passwordGenerationService.PasswordStrength(MasterPassword, userInput); var passwordStrength = _passwordGenerationService.PasswordStrength(MasterPassword, userInputs);
if (!await _policyService.EvaluateMasterPassword(passwordStrength.Score, MasterPassword, Policy)) if (!await _policyService.EvaluateMasterPassword(passwordStrength.Score, MasterPassword, Policy))
{ {
await Page.DisplayAlert(AppResources.MasterPasswordPolicyValidationTitle, await Page.DisplayAlert(AppResources.MasterPasswordPolicyValidationTitle,
@@ -148,7 +149,7 @@ namespace Bit.App.Pages
} }
else else
{ {
if (MasterPassword.Length < 8) if (MasterPassword.Length < Constants.MasterPasswordMinimumChars)
{ {
await Page.DisplayAlert(AppResources.MasterPasswordPolicyValidationTitle, await Page.DisplayAlert(AppResources.MasterPasswordPolicyValidationTitle,
AppResources.MasterPasswordLengthValMessage, AppResources.Ok); AppResources.MasterPasswordLengthValMessage, AppResources.Ok);
@@ -163,9 +164,8 @@ namespace Bit.App.Pages
} }
var kdf = KdfType.PBKDF2_SHA256; var kdf = KdfType.PBKDF2_SHA256;
var kdfIterations = 100000;
var email = await _stateService.GetEmailAsync(); var email = await _stateService.GetEmailAsync();
var key = await _cryptoService.MakeKeyAsync(MasterPassword, email, kdf, kdfIterations); var key = await _cryptoService.MakeKeyAsync(MasterPassword, email, kdf, Constants.KdfIterations);
var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.ServerAuthorization); var masterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.ServerAuthorization);
var localMasterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.LocalAuthorization); var localMasterPasswordHash = await _cryptoService.HashPasswordAsync(MasterPassword, key, HashPurpose.LocalAuthorization);
@@ -187,7 +187,7 @@ namespace Bit.App.Pages
Key = encKey.Item2.EncryptedString, Key = encKey.Item2.EncryptedString,
MasterPasswordHint = Hint, MasterPasswordHint = Hint,
Kdf = kdf, Kdf = kdf,
KdfIterations = kdfIterations, KdfIterations = Constants.KdfIterations,
OrgIdentifier = OrgIdentifier, OrgIdentifier = OrgIdentifier,
Keys = new KeysRequest Keys = new KeysRequest
{ {
@@ -202,7 +202,7 @@ namespace Bit.App.Pages
// Set Password and relevant information // Set Password and relevant information
await _apiService.SetPasswordAsync(request); await _apiService.SetPasswordAsync(request);
await _stateService.SetKdfTypeAsync(kdf); await _stateService.SetKdfTypeAsync(kdf);
await _stateService.SetKdfIterationsAsync(kdfIterations); await _stateService.SetKdfIterationsAsync(Constants.KdfIterations);
await _cryptoService.SetKeyAsync(key); await _cryptoService.SetKeyAsync(key);
await _cryptoService.SetKeyHashAsync(localMasterPasswordHash); await _cryptoService.SetKeyHashAsync(localMasterPasswordHash);
await _cryptoService.SetEncKeyAsync(encKey.Item2.EncryptedString); await _cryptoService.SetEncKeyAsync(encKey.Item2.EncryptedString);

View File

@@ -44,7 +44,7 @@
Margin="0" Margin="0"
HasShadow="False" HasShadow="False"
BackgroundColor="Transparent" BackgroundColor="Transparent"
BorderColor="Accent"> BorderColor="{DynamicResource PrimaryColor}">
<Label <Label
Text="{u:I18n UpdateMasterPasswordWarning}" Text="{u:I18n UpdateMasterPasswordWarning}"
StyleClass="text-muted, text-sm, text-bold" StyleClass="text-muted, text-sm, text-bold"
@@ -67,7 +67,7 @@
Margin="0" Margin="0"
HasShadow="False" HasShadow="False"
BackgroundColor="Transparent" BackgroundColor="Transparent"
BorderColor="Accent"> BorderColor="{DynamicResource PrimaryColor}">
<Label <Label
Text="{Binding PolicySummary}" Text="{Binding PolicySummary}"
StyleClass="text-muted, text-sm, text-bold" StyleClass="text-muted, text-sm, text-bold"

View File

@@ -129,8 +129,8 @@ namespace Bit.App.Pages
{ {
if (useCurrentActiveAccount) if (useCurrentActiveAccount)
{ {
return new AvatarImageSource(await _stateService.GetActiveUserIdAsync(), var user = await _stateService.GetActiveUserCustomDataAsync(a => (a?.Profile?.UserId, a?.Profile?.Name, a?.Profile?.Email, a?.Profile?.AvatarColor));
await _stateService.GetNameAsync(), await _stateService.GetEmailAsync()); return new AvatarImageSource(user.UserId, user.Name, user.Email, user.AvatarColor);
} }
return new AvatarImageSource(); return new AvatarImageSource();
} }

View File

@@ -1,4 +1,10 @@
using Bit.App.Controls; using System;
using Bit.App.Abstractions;
using Bit.App.Controls;
using Bit.App.Resources;
using Bit.Core.Abstractions;
using Bit.Core.Exceptions;
using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Xamarin.Forms; using Xamarin.Forms;
@@ -8,6 +14,9 @@ namespace Bit.App.Pages
{ {
private string _pageTitle = string.Empty; private string _pageTitle = string.Empty;
private AvatarImageSource _avatar; private AvatarImageSource _avatar;
private LazyResolve<IDeviceActionService> _deviceActionService = new LazyResolve<IDeviceActionService>();
private LazyResolve<IPlatformUtilsService> _platformUtilsService = new LazyResolve<IPlatformUtilsService>();
private LazyResolve<ILogger> _logger = new LazyResolve<ILogger>();
public string PageTitle public string PageTitle
{ {
@@ -22,5 +31,21 @@ namespace Bit.App.Pages
} }
public ContentPage Page { get; set; } public ContentPage Page { get; set; }
protected void HandleException(Exception ex, string message = null)
{
if (ex is ApiException apiException && apiException.Error != null)
{
message = apiException.Error.GetSingleMessage();
}
Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
{
await _deviceActionService.Value.HideLoadingAsync();
await _platformUtilsService.Value.ShowDialogAsync(message ?? AppResources.GenericErrorMessage);
}).FireAndForget();
_logger.Value.Exception(ex);
}
} }
} }

View File

@@ -16,6 +16,22 @@ namespace Bit.App.Pages
protected abstract IPlatformUtilsService platformUtilsService { get; } protected abstract IPlatformUtilsService platformUtilsService { get; }
protected string _captchaToken = null; protected string _captchaToken = null;
protected async Task<bool> HandleCaptchaAsync(string captchaSiteKey, bool needsCaptcha, Func<Task> onSuccess)
{
if (!needsCaptcha)
{
_captchaToken = null;
return false;
}
if (await HandleCaptchaAsync(captchaSiteKey))
{
await onSuccess();
_captchaToken = null;
}
return true;
}
protected async Task<bool> HandleCaptchaAsync(string CaptchaSiteKey) protected async Task<bool> HandleCaptchaAsync(string CaptchaSiteKey)
{ {
var callbackUri = "bitwarden://captcha-callback"; var callbackUri = "bitwarden://captcha-callback";

View File

@@ -66,7 +66,7 @@
Margin="0" Margin="0"
HasShadow="False" HasShadow="False"
BackgroundColor="Transparent" BackgroundColor="Transparent"
BorderColor="Accent"> BorderColor="{DynamicResource PrimaryColor}">
<Label <Label
Text="{u:I18n PasswordGeneratorPolicyInEffect}" Text="{u:I18n PasswordGeneratorPolicyInEffect}"
StyleClass="text-muted, text-sm, text-bold" StyleClass="text-muted, text-sm, text-bold"

View File

@@ -67,7 +67,7 @@
Margin="0, 12, 0, 0" Margin="0, 12, 0, 0"
HasShadow="False" HasShadow="False"
BackgroundColor="Transparent" BackgroundColor="Transparent"
BorderColor="Accent"> BorderColor="{DynamicResource PrimaryColor}">
<Label <Label
Text="{u:I18n SendDisabledWarning}" Text="{u:I18n SendDisabledWarning}"
StyleClass="text-muted, text-sm, text-bold" StyleClass="text-muted, text-sm, text-bold"
@@ -79,7 +79,7 @@
Margin="0, 12, 0, 0" Margin="0, 12, 0, 0"
HasShadow="False" HasShadow="False"
BackgroundColor="Transparent" BackgroundColor="Transparent"
BorderColor="Accent"> BorderColor="{DynamicResource PrimaryColor}">
<Label <Label
Text="{u:I18n SendOptionsPolicyInEffect}" Text="{u:I18n SendOptionsPolicyInEffect}"
StyleClass="text-muted, text-sm, text-bold" StyleClass="text-muted, text-sm, text-bold"

View File

@@ -48,7 +48,7 @@
Margin="0, 12, 0, 0" Margin="0, 12, 0, 0"
HasShadow="False" HasShadow="False"
BackgroundColor="Transparent" BackgroundColor="Transparent"
BorderColor="Accent"> BorderColor="{DynamicResource PrimaryColor}">
<Label <Label
Text="{u:I18n SendDisabledWarning}" Text="{u:I18n SendDisabledWarning}"
StyleClass="text-muted, text-sm, text-bold" StyleClass="text-muted, text-sm, text-bold"
@@ -60,7 +60,7 @@
Margin="0, 12, 0, 0" Margin="0, 12, 0, 0"
HasShadow="False" HasShadow="False"
BackgroundColor="Transparent" BackgroundColor="Transparent"
BorderColor="Accent"> BorderColor="{DynamicResource PrimaryColor}">
<Label <Label
Text="{u:I18n SendOptionsPolicyInEffect}" Text="{u:I18n SendOptionsPolicyInEffect}"
StyleClass="text-muted, text-sm, text-bold" StyleClass="text-muted, text-sm, text-bold"

View File

@@ -108,7 +108,7 @@
Margin="0, 12, 0, 6" Margin="0, 12, 0, 6"
HasShadow="False" HasShadow="False"
BackgroundColor="Transparent" BackgroundColor="Transparent"
BorderColor="Accent"> BorderColor="{DynamicResource PrimaryColor}">
<Label <Label
Text="{u:I18n SendDisabledWarning}" Text="{u:I18n SendDisabledWarning}"
StyleClass="text-muted, text-sm, text-bold" StyleClass="text-muted, text-sm, text-bold"

View File

@@ -34,7 +34,7 @@
Margin="0, 12, 0, 0" Margin="0, 12, 0, 0"
HasShadow="False" HasShadow="False"
BackgroundColor="Transparent" BackgroundColor="Transparent"
BorderColor="Accent"> BorderColor="{DynamicResource PrimaryColor}">
<Label <Label
Text="{u:I18n DisablePersonalVaultExportPolicyInEffect}" Text="{u:I18n DisablePersonalVaultExportPolicyInEffect}"
StyleClass="text-muted, text-sm, text-bold" StyleClass="text-muted, text-sm, text-bold"

View File

@@ -26,7 +26,7 @@
Padding="10" Padding="10"
HasShadow="False" HasShadow="False"
BackgroundColor="Transparent" BackgroundColor="Transparent"
BorderColor="Accent"> BorderColor="{DynamicResource PrimaryColor}">
<Label <Label
Text="{Binding Name, Mode=OneWay}" Text="{Binding Name, Mode=OneWay}"
StyleClass="text-muted, text-sm, text-bold" StyleClass="text-muted, text-sm, text-bold"
@@ -57,7 +57,7 @@
Padding="10" Padding="10"
HasShadow="False" HasShadow="False"
BackgroundColor="Transparent" BackgroundColor="Transparent"
BorderColor="Accent"> BorderColor="{DynamicResource PrimaryColor}">
<Label <Label
Text="{Binding Name, Mode=OneWay}" Text="{Binding Name, Mode=OneWay}"
StyleClass="text-muted, text-sm, text-bold" StyleClass="text-muted, text-sm, text-bold"

View File

@@ -7,7 +7,10 @@ using Bit.App.Pages.Accounts;
using Bit.App.Resources; using Bit.App.Resources;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Models;
using Bit.Core.Models.Domain; using Bit.Core.Models.Domain;
using Bit.Core.Models.View;
using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.ObjectModel; using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms; using Xamarin.Forms;
@@ -32,6 +35,7 @@ namespace Bit.App.Pages
private readonly IClipboardService _clipboardService; private readonly IClipboardService _clipboardService;
private readonly ILogger _loggerService; private readonly ILogger _loggerService;
private readonly IPushNotificationService _pushNotificationService; private readonly IPushNotificationService _pushNotificationService;
private readonly IWatchDeviceService _watchDeviceService;
private const int CustomVaultTimeoutValue = -100; private const int CustomVaultTimeoutValue = -100;
private bool _supportsBiometric; private bool _supportsBiometric;
@@ -44,6 +48,7 @@ namespace Bit.App.Pages
private bool _showChangeMasterPassword; private bool _showChangeMasterPassword;
private bool _reportLoggingEnabled; private bool _reportLoggingEnabled;
private bool _approvePasswordlessLoginRequests; private bool _approvePasswordlessLoginRequests;
private bool _shouldConnectToWatch;
private List<KeyValuePair<string, int?>> _vaultTimeouts = private List<KeyValuePair<string, int?>> _vaultTimeouts =
new List<KeyValuePair<string, int?>> new List<KeyValuePair<string, int?>>
@@ -87,6 +92,7 @@ namespace Bit.App.Pages
_clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService"); _clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
_loggerService = ServiceContainer.Resolve<ILogger>("logger"); _loggerService = ServiceContainer.Resolve<ILogger>("logger");
_pushNotificationService = ServiceContainer.Resolve<IPushNotificationService>(); _pushNotificationService = ServiceContainer.Resolve<IPushNotificationService>();
_watchDeviceService = ServiceContainer.Resolve<IWatchDeviceService>();
GroupedItems = new ObservableRangeCollection<ISettingsPageListItem>(); GroupedItems = new ObservableRangeCollection<ISettingsPageListItem>();
PageTitle = AppResources.Settings; PageTitle = AppResources.Settings;
@@ -138,6 +144,9 @@ namespace Bit.App.Pages
!await _keyConnectorService.GetUsesKeyConnector(); !await _keyConnectorService.GetUsesKeyConnector();
_reportLoggingEnabled = await _loggerService.IsEnabled(); _reportLoggingEnabled = await _loggerService.IsEnabled();
_approvePasswordlessLoginRequests = await _stateService.GetApprovePasswordlessLoginsAsync(); _approvePasswordlessLoginRequests = await _stateService.GetApprovePasswordlessLoginsAsync();
_shouldConnectToWatch = await _stateService.GetShouldConnectToWatchAsync();
BuildList(); BuildList();
} }
@@ -601,19 +610,26 @@ namespace Bit.App.Pages
ExecuteAsync = () => SetScreenCaptureAllowedAsync() ExecuteAsync = () => SetScreenCaptureAllowedAsync()
}); });
} }
var accountItems = new List<SettingsPageListItem> var accountItems = new List<SettingsPageListItem>();
if (Device.RuntimePlatform == Device.iOS)
{ {
new SettingsPageListItem accountItems.Add(new SettingsPageListItem
{
Name = AppResources.ConnectToWatch,
SubLabel = _shouldConnectToWatch ? AppResources.On : AppResources.Off,
ExecuteAsync = () => ToggleWatchConnectionAsync()
});
}
accountItems.Add(new SettingsPageListItem
{ {
Name = AppResources.FingerprintPhrase, Name = AppResources.FingerprintPhrase,
ExecuteAsync = () => FingerprintAsync() ExecuteAsync = () => FingerprintAsync()
}, });
new SettingsPageListItem accountItems.Add(new SettingsPageListItem
{ {
Name = AppResources.LogOut, Name = AppResources.LogOut,
ExecuteAsync = () => LogOutAsync() ExecuteAsync = () => LogOutAsync()
} });
};
if (_showChangeMasterPassword) if (_showChangeMasterPassword)
{ {
accountItems.Insert(0, new SettingsPageListItem accountItems.Insert(0, new SettingsPageListItem
@@ -791,5 +807,13 @@ namespace Bit.App.Pages
await Page.DisplayAlert(AppResources.AnErrorHasOccurred, AppResources.GenericErrorMessage, AppResources.Ok); await Page.DisplayAlert(AppResources.AnErrorHasOccurred, AppResources.GenericErrorMessage, AppResources.Ok);
} }
} }
private async Task ToggleWatchConnectionAsync()
{
_shouldConnectToWatch = !_shouldConnectToWatch;
await _watchDeviceService.SetShouldConnectToWatchAsync(_shouldConnectToWatch);
BuildList();
}
} }
} }

View File

@@ -96,7 +96,7 @@
Margin="0" Margin="0"
HasShadow="False" HasShadow="False"
BackgroundColor="Transparent" BackgroundColor="Transparent"
BorderColor="Accent"> BorderColor="{DynamicResource PrimaryColor}">
<Label <Label
Text="{u:I18n PersonalOwnershipPolicyInEffect}" Text="{u:I18n PersonalOwnershipPolicyInEffect}"
StyleClass="text-muted, text-sm, text-bold" StyleClass="text-muted, text-sm, text-bold"

View File

@@ -263,12 +263,6 @@ namespace Bit.App.Pages
{ {
if (DoOnce()) if (DoOnce())
{ {
var cameraPermission = await PermissionManager.CheckAndRequestPermissionAsync(new Permissions.Camera());
if (cameraPermission != PermissionStatus.Granted)
{
return;
}
var page = new ScanPage(key => var page = new ScanPage(key =>
{ {
Device.BeginInvokeOnMainThread(async () => Device.BeginInvokeOnMainThread(async () =>
@@ -277,6 +271,7 @@ namespace Bit.App.Pages
await _vm.UpdateTotpKeyAsync(key); await _vm.UpdateTotpKeyAsync(key);
}); });
}); });
await Navigation.PushModalAsync(new Xamarin.Forms.NavigationPage(page)); await Navigation.PushModalAsync(new Xamarin.Forms.NavigationPage(page));
} }
} }

View File

@@ -29,6 +29,7 @@ namespace Bit.App.Pages
private readonly ICustomFieldItemFactory _customFieldItemFactory; private readonly ICustomFieldItemFactory _customFieldItemFactory;
private readonly IClipboardService _clipboardService; private readonly IClipboardService _clipboardService;
private readonly IAutofillHandler _autofillHandler; private readonly IAutofillHandler _autofillHandler;
private readonly IWatchDeviceService _watchDeviceService;
private bool _showNotesSeparator; private bool _showNotesSeparator;
private bool _showPassword; private bool _showPassword;
@@ -80,6 +81,7 @@ namespace Bit.App.Pages
_customFieldItemFactory = ServiceContainer.Resolve<ICustomFieldItemFactory>("customFieldItemFactory"); _customFieldItemFactory = ServiceContainer.Resolve<ICustomFieldItemFactory>("customFieldItemFactory");
_clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService"); _clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
_autofillHandler = ServiceContainer.Resolve<IAutofillHandler>(); _autofillHandler = ServiceContainer.Resolve<IAutofillHandler>();
_watchDeviceService = ServiceContainer.Resolve<IWatchDeviceService>();
GeneratePasswordCommand = new Command(GeneratePassword); GeneratePasswordCommand = new Command(GeneratePassword);
TogglePasswordCommand = new Command(TogglePassword); TogglePasswordCommand = new Command(TogglePassword);
@@ -137,6 +139,7 @@ namespace Bit.App.Pages
new KeyValuePair<string, string>(AppResources.Mr, AppResources.Mr), new KeyValuePair<string, string>(AppResources.Mr, AppResources.Mr),
new KeyValuePair<string, string>(AppResources.Mrs, AppResources.Mrs), new KeyValuePair<string, string>(AppResources.Mrs, AppResources.Mrs),
new KeyValuePair<string, string>(AppResources.Ms, AppResources.Ms), new KeyValuePair<string, string>(AppResources.Ms, AppResources.Ms),
new KeyValuePair<string, string>(AppResources.Mx, AppResources.Mx),
new KeyValuePair<string, string>(AppResources.Dr, AppResources.Dr), new KeyValuePair<string, string>(AppResources.Dr, AppResources.Dr),
}; };
FolderOptions = new List<KeyValuePair<string, string>>(); FolderOptions = new List<KeyValuePair<string, string>>();
@@ -507,6 +510,8 @@ namespace Bit.App.Pages
EditMode && !CloneMode ? AppResources.ItemUpdated : AppResources.NewItemCreated); EditMode && !CloneMode ? AppResources.ItemUpdated : AppResources.NewItemCreated);
_messagingService.Send(EditMode && !CloneMode ? "editedCipher" : "addedCipher", Cipher.Id); _messagingService.Send(EditMode && !CloneMode ? "editedCipher" : "addedCipher", Cipher.Id);
_watchDeviceService.SyncDataToWatchAsync().FireAndForget();
if (Page is CipherAddEditPage page && page.FromAutofillFramework) if (Page is CipherAddEditPage page && page.FromAutofillFramework)
{ {
// Close and go back to app // Close and go back to app

View File

@@ -31,6 +31,7 @@ namespace Bit.App.Pages
private readonly ILocalizeService _localizeService; private readonly ILocalizeService _localizeService;
private readonly ICustomFieldItemFactory _customFieldItemFactory; private readonly ICustomFieldItemFactory _customFieldItemFactory;
private readonly IClipboardService _clipboardService; private readonly IClipboardService _clipboardService;
private readonly IWatchDeviceService _watchDeviceService;
private List<ICustomFieldItemViewModel> _fields; private List<ICustomFieldItemViewModel> _fields;
private bool _canAccessPremium; private bool _canAccessPremium;
@@ -62,6 +63,7 @@ namespace Bit.App.Pages
_localizeService = ServiceContainer.Resolve<ILocalizeService>("localizeService"); _localizeService = ServiceContainer.Resolve<ILocalizeService>("localizeService");
_customFieldItemFactory = ServiceContainer.Resolve<ICustomFieldItemFactory>("customFieldItemFactory"); _customFieldItemFactory = ServiceContainer.Resolve<ICustomFieldItemFactory>("customFieldItemFactory");
_clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService"); _clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
_watchDeviceService = ServiceContainer.Resolve<IWatchDeviceService>();
CopyCommand = new AsyncCommand<string>((id) => CopyAsync(id, null), onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false); CopyCommand = new AsyncCommand<string>((id) => CopyAsync(id, null), onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false);
CopyUriCommand = new AsyncCommand<LoginUriView>(uriView => CopyAsync("LoginUri", uriView.Uri), onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false); CopyUriCommand = new AsyncCommand<LoginUriView>(uriView => CopyAsync("LoginUri", uriView.Uri), onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false);
@@ -371,6 +373,9 @@ namespace Bit.App.Pages
await _cipherService.SoftDeleteWithServerAsync(Cipher.Id); await _cipherService.SoftDeleteWithServerAsync(Cipher.Id);
} }
await _deviceActionService.HideLoadingAsync(); await _deviceActionService.HideLoadingAsync();
_watchDeviceService.SyncDataToWatchAsync().FireAndForget();
_platformUtilsService.ShowToast("success", null, _platformUtilsService.ShowToast("success", null,
Cipher.IsDeleted ? AppResources.ItemDeleted : AppResources.ItemSoftDeleted); Cipher.IsDeleted ? AppResources.ItemDeleted : AppResources.ItemSoftDeleted);
_messagingService.Send(Cipher.IsDeleted ? "deletedCipher" : "softDeletedCipher", Cipher); _messagingService.Send(Cipher.IsDeleted ? "deletedCipher" : "softDeletedCipher", Cipher);

View File

@@ -108,6 +108,10 @@ namespace Bit.App.Pages
else if (message.Command == "syncCompleted") else if (message.Command == "syncCompleted")
{ {
await Task.Delay(500); await Task.Delay(500);
if (_vm.MainPage)
{
_vm.AvatarImageSource = await GetAvatarImageSourceAsync();
}
Device.BeginInvokeOnMainThread(() => Device.BeginInvokeOnMainThread(() =>
{ {
IsBusy = false; IsBusy = false;

View File

@@ -34,16 +34,13 @@
<RowDefinition Height="*" /> <RowDefinition Height="*" />
<RowDefinition Height="*" /> <RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<zxing:ZXingScannerView <ContentView
x:Name="_zxing" x:Name="_scannerContainer"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
AutomationId="zxingScannerView" AutomationId="zxingScannerView"
IsVisible="{Binding ShowScanner}" IsVisible="{Binding ShowScanner}"
Grid.Column="0" Grid.Column="0"
Grid.Row="0" Grid.Row="0"
Grid.RowSpan="3" Grid.RowSpan="3"/>
OnScanResult="OnScanResult"/>
<StackLayout <StackLayout
VerticalOptions="Center" VerticalOptions="Center"
HorizontalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"

View File

@@ -8,8 +8,10 @@ using Bit.Core.Abstractions;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using SkiaSharp; using SkiaSharp;
using SkiaSharp.Views.Forms; using SkiaSharp.Views.Forms;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Essentials; using Xamarin.Essentials;
using Xamarin.Forms; using Xamarin.Forms;
using ZXing.Net.Mobile.Forms;
namespace Bit.App.Pages namespace Bit.App.Pages
{ {
@@ -26,20 +28,15 @@ namespace Bit.App.Pages
private bool _pageIsActive; private bool _pageIsActive;
private bool _qrcodeFound; private bool _qrcodeFound;
private float _scale; private float _scale;
private ZXingScannerView _zxing;
private readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>("logger"); private readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>("logger");
public ScanPage(Action<string> callback) public ScanPage(Action<string> callback)
{ {
_callback = callback;
InitializeComponent(); InitializeComponent();
_zxing.Options = new ZXing.Mobile.MobileBarcodeScanningOptions _callback = callback;
{ ViewModel.InitScannerCommand = new Command(() => InitScanner());
UseNativeScanning = true,
PossibleFormats = new List<ZXing.BarcodeFormat> { ZXing.BarcodeFormat.QR_CODE },
AutoRotate = false,
TryInverted = true
};
if (Device.RuntimePlatform == Device.Android) if (Device.RuntimePlatform == Device.Android)
{ {
ToolbarItems.RemoveAt(0); ToolbarItems.RemoveAt(0);
@@ -55,6 +52,53 @@ namespace Bit.App.Pages
protected override void OnAppearing() protected override void OnAppearing()
{ {
base.OnAppearing(); base.OnAppearing();
StartScanner();
}
protected override void OnDisappearing()
{
StopScanner().FireAndForget();
base.OnDisappearing();
}
// Fix known bug with DelayBetweenAnalyzingFrames & DelayBetweenContinuousScans: https://github.com/Redth/ZXing.Net.Mobile/issues/721
private void InitScanner()
{
try
{
if (!ViewModel.HasCameraPermission || !ViewModel.ShowScanner || _zxing != null)
{
return;
}
_zxing = new ZXingScannerView();
_zxing.Options = new ZXing.Mobile.MobileBarcodeScanningOptions
{
UseNativeScanning = true,
PossibleFormats = new List<ZXing.BarcodeFormat> { ZXing.BarcodeFormat.QR_CODE },
AutoRotate = false,
TryInverted = true,
DelayBetweenAnalyzingFrames = 5,
DelayBetweenContinuousScans = 5
};
_scannerContainer.Content = _zxing;
StartScanner();
}
catch (Exception ex)
{
_logger.Value.Exception(ex);
}
}
private void StartScanner()
{
if (_zxing == null)
{
return;
}
_zxing.OnScanResult -= OnScanResult;
_zxing.OnScanResult += OnScanResult;
_zxing.IsScanning = true; _zxing.IsScanning = true;
// Fix for Autofocus, now it's done every 2 seconds so that the user does't have to do it // Fix for Autofocus, now it's done every 2 seconds so that the user does't have to do it
@@ -98,16 +142,21 @@ namespace Bit.App.Pages
AnimationLoopAsync(); AnimationLoopAsync();
} }
protected override async void OnDisappearing() private async Task StopScanner()
{ {
if (_zxing == null)
{
return;
}
_autofocusCts?.Cancel(); _autofocusCts?.Cancel();
if (_continuousAutofocusTask != null) if (_continuousAutofocusTask != null)
{ {
await _continuousAutofocusTask; await _continuousAutofocusTask;
} }
_zxing.IsScanning = false; _zxing.IsScanning = false;
_zxing.OnScanResult -= OnScanResult;
_pageIsActive = false; _pageIsActive = false;
base.OnDisappearing();
} }
private async void OnScanResult(ZXing.Result result) private async void OnScanResult(ZXing.Result result)

View File

@@ -1,6 +1,14 @@
using Bit.App.Resources; using System;
using System.Threading.Tasks;
using System.Windows.Input;
using Bit.App.Abstractions;
using Bit.App.Resources;
using Bit.App.Utilities; using Bit.App.Utilities;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Essentials;
using Xamarin.Forms; using Xamarin.Forms;
namespace Bit.App.Pages namespace Bit.App.Pages
@@ -9,13 +17,46 @@ namespace Bit.App.Pages
{ {
private bool _showScanner = true; private bool _showScanner = true;
private string _totpAuthenticationKey; private string _totpAuthenticationKey;
private IPlatformUtilsService _platformUtilsService;
private IDeviceActionService _deviceActionService;
private ILogger _logger;
public ScanPageViewModel() public ScanPageViewModel()
{ {
ToggleScanModeCommand = new Command(() => ShowScanner = !ShowScanner); ToggleScanModeCommand = new AsyncCommand(ToggleScanMode, onException: HandleException);
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
_logger = ServiceContainer.Resolve<ILogger>();
InitAsync().FireAndForget();
} }
public Command ToggleScanModeCommand { get; set; } public async Task InitAsync()
{
try
{
await Device.InvokeOnMainThreadAsync(async () =>
{
var hasCameraPermission = await PermissionManager.CheckAndRequestPermissionAsync(new Permissions.Camera());
HasCameraPermission = hasCameraPermission == PermissionStatus.Granted;
ShowScanner = hasCameraPermission == PermissionStatus.Granted;
});
if (!HasCameraPermission)
{
return;
}
InitScannerCommand.Execute(null);
}
catch (System.Exception ex)
{
HandleException(ex);
}
}
public ICommand ToggleScanModeCommand { get; set; }
public ICommand InitScannerCommand { get; set; }
public bool HasCameraPermission { get; set; }
public string ScanQrPageTitle => ShowScanner ? AppResources.ScanQrTitle : AppResources.AuthenticatorKeyScanner; public string ScanQrPageTitle => ShowScanner ? AppResources.ScanQrTitle : AppResources.AuthenticatorKeyScanner;
public string CameraInstructionTop => ShowScanner ? AppResources.PointYourCameraAtTheQRCode : AppResources.OnceTheKeyIsSuccessfullyEntered; public string CameraInstructionTop => ShowScanner ? AppResources.PointYourCameraAtTheQRCode : AppResources.OnceTheKeyIsSuccessfullyEntered;
public string TotpAuthenticationKey public string TotpAuthenticationKey
@@ -39,6 +80,23 @@ namespace Bit.App.Pages
}); });
} }
private async Task ToggleScanMode()
{
var cameraPermission = await PermissionManager.CheckAndRequestPermissionAsync(new Permissions.Camera());
HasCameraPermission = cameraPermission == PermissionStatus.Granted;
if (!HasCameraPermission)
{
var openAppSettingsResult = await _platformUtilsService.ShowDialogAsync(AppResources.EnableCamerPermissionToUseTheScanner, title: string.Empty, confirmText: AppResources.Settings, cancelText: AppResources.NoThanks);
if (openAppSettingsResult)
{
_deviceActionService.OpenAppSettings();
}
return;
}
ShowScanner = !ShowScanner;
InitScannerCommand.Execute(null);
}
public FormattedString ToggleScanModeLabel public FormattedString ToggleScanModeLabel
{ {
get get
@@ -57,5 +115,15 @@ namespace Bit.App.Pages
return fs; return fs;
} }
} }
private void HandleException(Exception ex)
{
Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () =>
{
await _deviceActionService.HideLoadingAsync();
await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage);
}).FireAndForget();
_logger.Exception(ex);
}
} }
} }

View File

@@ -481,6 +481,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to A notification has been sent to your device..
/// </summary>
public static string ANotificationHasBeenSentToYourDevice {
get {
return ResourceManager.GetString("ANotificationHasBeenSentToYourDevice", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to API access token. /// Looks up a localized string similar to API access token.
/// </summary> /// </summary>
@@ -1363,6 +1372,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Check known data breaches for this password.
/// </summary>
public static string CheckKnownDataBreachesForThisPassword {
get {
return ResourceManager.GetString("CheckKnownDataBreachesForThisPassword", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Check if password has been exposed.. /// Looks up a localized string similar to Check if password has been exposed..
/// </summary> /// </summary>
@@ -1489,6 +1507,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Connect to Watch.
/// </summary>
public static string ConnectToWatch {
get {
return ResourceManager.GetString("ConnectToWatch", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Continue. /// Looks up a localized string similar to Continue.
/// </summary> /// </summary>
@@ -2119,6 +2146,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Enable camera permission to use the scanner.
/// </summary>
public static string EnableCamerPermissionToUseTheScanner {
get {
return ResourceManager.GetString("EnableCamerPermissionToUseTheScanner", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Enabled. /// Looks up a localized string similar to Enabled.
/// </summary> /// </summary>
@@ -2389,6 +2425,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Exposed Master Password.
/// </summary>
public static string ExposedMasterPassword {
get {
return ResourceManager.GetString("ExposedMasterPassword", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Extension activated!. /// Looks up a localized string similar to Extension activated!.
/// </summary> /// </summary>
@@ -2911,6 +2956,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Good.
/// </summary>
public static string Good {
get {
return ResourceManager.GetString("Good", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Go to my vault. /// Looks up a localized string similar to Go to my vault.
/// </summary> /// </summary>
@@ -3046,6 +3100,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Important.
/// </summary>
public static string Important {
get {
return ResourceManager.GetString("Important", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Import items. /// Looks up a localized string similar to Import items.
/// </summary> /// </summary>
@@ -3480,6 +3543,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Log in initiated.
/// </summary>
public static string LogInInitiated {
get {
return ResourceManager.GetString("LogInInitiated", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Login. /// Looks up a localized string similar to Login.
/// </summary> /// </summary>
@@ -3526,7 +3598,7 @@ namespace Bit.App.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Enterprise Single Sign-On. /// Looks up a localized string similar to Enterprise single sign-on.
/// </summary> /// </summary>
public static string LogInSso { public static string LogInSso {
get { get {
@@ -3571,7 +3643,7 @@ namespace Bit.App.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Log In with master password. /// Looks up a localized string similar to Log in with master password.
/// </summary> /// </summary>
public static string LogInWithMasterPassword { public static string LogInWithMasterPassword {
get { get {
@@ -3912,6 +3984,17 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Mx.
/// </summary>
public static string Mx
{
get
{
return ResourceManager.GetString("Mx", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to You must log into the main Bitwarden app before you can use the extension.. /// Looks up a localized string similar to You must log into the main Bitwarden app before you can use the extension..
/// </summary> /// </summary>
@@ -3966,6 +4049,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Need another option?.
/// </summary>
public static string NeedAnotherOption {
get {
return ResourceManager.GetString("NeedAnotherOption", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Never. /// Looks up a localized string similar to Never.
/// </summary> /// </summary>
@@ -4525,6 +4617,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?.
/// </summary>
public static string PasswordFoundInADataBreachAlertDescription {
get {
return ResourceManager.GetString("PasswordFoundInADataBreachAlertDescription", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Password generated. /// Looks up a localized string similar to Password generated.
/// </summary> /// </summary>
@@ -4705,6 +4806,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device..
/// </summary>
public static string PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice {
get {
return ResourceManager.GetString("PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Plus addressed email. /// Looks up a localized string similar to Plus addressed email.
/// </summary> /// </summary>
@@ -5003,6 +5113,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Resend notification.
/// </summary>
public static string ResendNotification {
get {
return ResourceManager.GetString("ResendNotification", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password.. /// Looks up a localized string similar to This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password..
/// </summary> /// </summary>
@@ -5192,15 +5311,6 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to .
/// </summary>
public static string SelectAddTotpToStoreTheKeySafely {
get {
return ResourceManager.GetString("SelectAddTotpToStoreTheKeySafely", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to You must select at least one collection.. /// Looks up a localized string similar to You must select at least one collection..
/// </summary> /// </summary>
@@ -5615,6 +5725,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Strong.
/// </summary>
public static string Strong {
get {
return ResourceManager.GetString("Strong", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Submit. /// Looks up a localized string similar to Submit.
/// </summary> /// </summary>
@@ -5831,6 +5950,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to This request is no longer valid.
/// </summary>
public static string ThisRequestIsNoLongerValid {
get {
return ResourceManager.GetString("ThisRequestIsNoLongerValid", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to 3 days. /// Looks up a localized string similar to 3 days.
/// </summary> /// </summary>
@@ -6542,6 +6670,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to View all log in options.
/// </summary>
public static string ViewAllLoginOptions {
get {
return ResourceManager.GetString("ViewAllLoginOptions", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to View item. /// Looks up a localized string similar to View item.
/// </summary> /// </summary>
@@ -6578,6 +6715,51 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Weak.
/// </summary>
public static string Weak {
get {
return ResourceManager.GetString("Weak", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Weak and Exposed Master Password.
/// </summary>
public static string WeakAndExposedMasterPassword {
get {
return ResourceManager.GetString("WeakAndExposedMasterPassword", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Weak Master Password.
/// </summary>
public static string WeakMasterPassword {
get {
return ResourceManager.GetString("WeakMasterPassword", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?.
/// </summary>
public static string WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription {
get {
return ResourceManager.GetString("WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password?.
/// </summary>
public static string WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount {
get {
return ResourceManager.GetString("WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Website. /// Looks up a localized string similar to Website.
/// </summary> /// </summary>
@@ -6695,6 +6877,15 @@ namespace Bit.App.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Your master password cannot be recovered if you forget it! {0} characters minimum..
/// </summary>
public static string YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum {
get {
return ResourceManager.GetString("YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to To continue, hold your YubiKey NEO against the back of the device or insert your YubiKey into your device&apos;s USB port, then touch its button.. /// Looks up a localized string similar to To continue, hold your YubiKey NEO against the back of the device or insert your YubiKey into your device&apos;s USB port, then touch its button..
/// </summary> /// </summary>

View File

@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} is gekopieer.</value> <value>{0} is gekopieer.</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Bevestig vingerafdruk</value> <value>Bevestig vingerafdruk</value>
@@ -1576,7 +1576,7 @@ Skandering gebeur outomaties.</value>
<comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment> <comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment>
</data> </data>
<data name="SolarizedDark" xml:space="preserve"> <data name="SolarizedDark" xml:space="preserve">
<value>Solarized Dark</value> <value>'Solarized' Donker</value>
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment> <comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
</data> </data>
<data name="AutofillBlockedUris" xml:space="preserve"> <data name="AutofillBlockedUris" xml:space="preserve">
@@ -2299,9 +2299,6 @@ Skandering gebeur outomaties.</value>
<value>Sodra u die sleutel reg ingevoer het, <value>Sodra u die sleutel reg ingevoer het,
kies u Voeg TOTP toe om die sleutel veilig te bewaar</value> kies u Voeg TOTP toe om die sleutel veilig te bewaar</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Deur u vergrendelopsies na “Nooit” te stel, is u kluis beskikbaar aan enigeen met toegang tot u toestel. Indien u hierdie opsie gebruik moet u seker maak dat u u toestel voldoende beskerm.</value> <value>Deur u vergrendelopsies na “Nooit” te stel, is u kluis beskikbaar aan enigeen met toegang tot u toestel. Indien u hierdie opsie gebruik moet u seker maak dat u u toestel voldoende beskerm.</value>
</data> </data>
@@ -2452,6 +2449,9 @@ kies u Voeg TOTP toe om die sleutel veilig te bewaar</value>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Lukraak</value> <value>Lukraak</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Koppel aan horlosie</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Toeganklikheidsdiensopenbaarmaking</value> <value>Toeganklikheidsdiensopenbaarmaking</value>
</data> </data>
@@ -2468,8 +2468,50 @@ kies u Voeg TOTP toe om die sleutel veilig te bewaar</value>
<value>Aantekenversoek het reeds verstryk.</value> <value>Aantekenversoek het reeds verstryk.</value>
</data> </data>
<data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve"> <data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve">
<value>Login attempt from: <value>Teken Aan probeerslag van:
{0} {0}
Do you want to switch to this account?</value> Wil u na die rekening omskakel?</value>
</data>
<data name="NewAroundHere" xml:space="preserve">
<value>Nuut hier?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Kry hoofwagwoord wenk</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Teken in as {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Nie jy nie?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Teken aan met hoofwagwoord</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Teken Aan met 'n ander toestel</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Aanmelding begin</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>'n Kennisgewing was gestuur na u toestel.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Asseblief maak seker jou kluis is oopgesluit en die vingerafdruk frase stem ooreen op die ander toestel.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Stuur kennisgewing weer</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Is daar nog 'n opsie nodig?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Wys alle aanmeldings opsies</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Hierdie versoek is nie langer gelding nie</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Laat die kamera versoek toe om die skandeerder te gebruik</value>
</data> </data>
</root> </root>

View File

@@ -118,17 +118,17 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="About" xml:space="preserve"> <data name="About" xml:space="preserve">
<value>حول</value> <value>عن التطبيق</value>
</data> </data>
<data name="Add" xml:space="preserve"> <data name="Add" xml:space="preserve">
<value>إضافة</value> <value>أضِف</value>
<comment>Add/create a new entity (verb).</comment> <comment>Add/create a new entity (verb).</comment>
</data> </data>
<data name="AddFolder" xml:space="preserve"> <data name="AddFolder" xml:space="preserve">
<value>إضافة مجلد</value> <value>مجلد مضاف</value>
</data> </data>
<data name="AddItem" xml:space="preserve"> <data name="AddItem" xml:space="preserve">
<value>إضافة عنصر</value> <value>تمت إضافة العنصر</value>
<comment>The title for the add item page.</comment> <comment>The title for the add item page.</comment>
</data> </data>
<data name="AnErrorHasOccurred" xml:space="preserve"> <data name="AnErrorHasOccurred" xml:space="preserve">
@@ -323,14 +323,14 @@
<comment>Label for a password.</comment> <comment>Label for a password.</comment>
</data> </data>
<data name="Save" xml:space="preserve"> <data name="Save" xml:space="preserve">
<value>تسجيل</value> <value>حفظ</value>
<comment>Button text for a save operation (verb).</comment> <comment>Button text for a save operation (verb).</comment>
</data> </data>
<data name="Move" xml:space="preserve"> <data name="Move" xml:space="preserve">
<value>نقل</value> <value>نقل</value>
</data> </data>
<data name="Saving" xml:space="preserve"> <data name="Saving" xml:space="preserve">
<value>تسجيل ...</value> <value>حفظ...</value>
<comment>Message shown when interacting with the server</comment> <comment>Message shown when interacting with the server</comment>
</data> </data>
<data name="Settings" xml:space="preserve"> <data name="Settings" xml:space="preserve">
@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} تم نسخه</value> <value>{0} تم نسخه</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>التحقق من بصمة الإصبع</value> <value>التحقق من بصمة الإصبع</value>
@@ -2300,9 +2300,6 @@
<value>بمجرد إدخال المفتاح بنجاح، <value>بمجرد إدخال المفتاح بنجاح،
حدد إضافة TOTP لتخزين المفتاح بأمان</value> حدد إضافة TOTP لتخزين المفتاح بأمان</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>تعيين خيارات قفل الخاص بك إلى "مطلقا" يبقي خزنتك متاحةً لأي شخص لديه حق الوصول إلى جهازك. إذا كنت تستخدم هذا الخيار، يجب أن تتأكد من الحفاظ على حماية جهازك بشكل صحيح.</value> <value>تعيين خيارات قفل الخاص بك إلى "مطلقا" يبقي خزنتك متاحةً لأي شخص لديه حق الوصول إلى جهازك. إذا كنت تستخدم هذا الخيار، يجب أن تتأكد من الحفاظ على حماية جهازك بشكل صحيح.</value>
</data> </data>
@@ -2453,6 +2450,9 @@
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>عشوائي</value> <value>عشوائي</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>متّصل بالسّاعة</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>كشف خدمة إمكانية الوصول</value> <value>كشف خدمة إمكانية الوصول</value>
</data> </data>
@@ -2473,4 +2473,46 @@
{0} {0}
هل تريد التبديل إلى هذا الحساب؟</value> هل تريد التبديل إلى هذا الحساب؟</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>جديد هنا؟</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>احصل على تلميح كلمة المرور الرئيسية</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>تسجيل الدخول كـ {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>ليس أنت؟</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>تسجيل الدخول باستخدام كلمة المرور الرئيسية</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>تسجيل الدخول باستخدام جهاز آخر</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>بدء تسجيل الدخول</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>تم إرسال إشعار إلى جهازك.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>الرجاء التأكد من أن الخزنة الخاصة بك غير مقفلة وأن عبارة بصمة الإصبع تتطابق على الجهاز الآخر.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>إعادة إرسال الإشعار</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>هل تحتاج إلى خيار آخر؟</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>عرض جميع خيارات تسجيل الدخول</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>هذا الطلب لم يعد صالحًا</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>تمكين إذن الكاميرا لاستخدام الماسح الضوئي</value>
</data>
</root> </root>

View File

@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} kopyalandı.</value> <value>{0} kopyalandı.</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Barmaq izini təsdiqlə</value> <value>Barmaq izini təsdiqlə</value>
@@ -2137,7 +2137,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
<value>Bu təşkilat, sizi "parol sıfırlama"da avtomatik olaraq qeydiyyata alan müəssisə siyasətinə sahibdir. Qeydiyyat, təşkilat administratorlarına ana parolunuzu dəyişdirmə icazəsi verəcək.</value> <value>Bu təşkilat, sizi "parol sıfırlama"da avtomatik olaraq qeydiyyata alan müəssisə siyasətinə sahibdir. Qeydiyyat, təşkilat administratorlarına ana parolunuzu dəyişdirmə icazəsi verəcək.</value>
</data> </data>
<data name="VaultTimeoutPolicyInEffect" xml:space="preserve"> <data name="VaultTimeoutPolicyInEffect" xml:space="preserve">
<value>Təşkilatınızın siyasətləri, anbarınızın vaxt bitişinə təsir edir. Anbar vaxt bitişi üçün icazə verilən maksimum vaxt $HOURS$ saat $MINUTES$ dəqiqədir</value> <value>Your organization policies are affecting your vault timeout. Maximum allowed vault timeout is {0} hour(s) and {1} minute(s)</value>
</data> </data>
<data name="VaultTimeoutToLarge" xml:space="preserve"> <data name="VaultTimeoutToLarge" xml:space="preserve">
<value>Anbar vaxt bitişi, təşkilatınız tərəfindən tənzimlənən məhdudiyyətləri aşır.</value> <value>Anbar vaxt bitişi, təşkilatınız tərəfindən tənzimlənən məhdudiyyətləri aşır.</value>
@@ -2298,9 +2298,6 @@ Skan prosesi avtomatik baş tutacaq.</value>
<data name="OnceTheKeyIsSuccessfullyEntered" xml:space="preserve"> <data name="OnceTheKeyIsSuccessfullyEntered" xml:space="preserve">
<value>Açar uğurla daxil edildikdən sonra, açarı güvənli şəkildə saxlamaq üçün "TOTP əlavə et"i seçin</value> <value>Açar uğurla daxil edildikdən sonra, açarı güvənli şəkildə saxlamaq üçün "TOTP əlavə et"i seçin</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Kilid seçimlərini "Heç vaxt" olaraq tənzimləmək, anbarınızı cihazınıza müraciəti olan hər kəsə əlçatan edir. Bu seçimi istifadə etsəniz, cihazınızı düzgün qoruduğunuza əmin olmalısınız.</value> <value>Kilid seçimlərini "Heç vaxt" olaraq tənzimləmək, anbarınızı cihazınıza müraciəti olan hər kəsə əlçatan edir. Bu seçimi istifadə etsəniz, cihazınızı düzgün qoruduğunuza əmin olmalısınız.</value>
</data> </data>
@@ -2451,6 +2448,9 @@ Skan prosesi avtomatik baş tutacaq.</value>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Təsadüfi</value> <value>Təsadüfi</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>"Watch"a bağlan</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Əlçatımlılıq Xidməti açıqlaması</value> <value>Əlçatımlılıq Xidməti açıqlaması</value>
</data> </data>
@@ -2471,4 +2471,46 @@ Skan prosesi avtomatik baş tutacaq.</value>
{0} {0}
Bu hesaba keçmək istəyirsiniz?</value> Bu hesaba keçmək istəyirsiniz?</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>Burada yenisiniz?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Ana parol üçün məsləhət alın</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>{0} olaraq giriş edilir</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Siz deyilsiniz?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Ana parolla giriş et</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Başqa cihazla giriş et</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Giriş etmə başladıldı</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Cihazınıza bir bildiriş göndərildi.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Zəhmət olmasa anbarınızın kilidinin açıq olduğuna və Barmaq izi ifadəsinin digər cihazda uyğun gəldiyinə əmin olun.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Bildirişi təkrar göndər</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Başqa bir seçimə ehtiyacınız var?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Bütün giriş etmə seçimlərinə bax</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Bu tələb artıq yararsızdır</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Skaneri istifadə etmək üçün kamera icazəsini fəallaşdırın</value>
</data>
</root> </root>

View File

@@ -349,7 +349,7 @@
<value>Адправіць</value> <value>Адправіць</value>
</data> </data>
<data name="Sync" xml:space="preserve"> <data name="Sync" xml:space="preserve">
<value>Сінхранізавана</value> <value>Сінхранізаваць</value>
<comment>The title for the sync page.</comment> <comment>The title for the sync page.</comment>
</data> </data>
<data name="ThankYou" xml:space="preserve"> <data name="ThankYou" xml:space="preserve">
@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} скапіяваны</value> <value>{0} скапіяваны</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Праверка адбітка пальца</value> <value>Праверка адбітка пальца</value>
@@ -1575,7 +1575,7 @@
<comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment> <comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment>
</data> </data>
<data name="SolarizedDark" xml:space="preserve"> <data name="SolarizedDark" xml:space="preserve">
<value>Цёмная Solarized</value> <value>Solarized Dark</value>
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment> <comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
</data> </data>
<data name="AutofillBlockedUris" xml:space="preserve"> <data name="AutofillBlockedUris" xml:space="preserve">
@@ -1622,7 +1622,7 @@
<value>Біяметрычныя праверка</value> <value>Біяметрычныя праверка</value>
</data> </data>
<data name="Biometrics" xml:space="preserve"> <data name="Biometrics" xml:space="preserve">
<value>Біяметрыяй</value> <value>біяметрыяй</value>
</data> </data>
<data name="UseBiometricsToUnlock" xml:space="preserve"> <data name="UseBiometricsToUnlock" xml:space="preserve">
<value>Выкарыстоўваць біяметрычныя даныя для разблакіроўкі</value> <value>Выкарыстоўваць біяметрычныя даныя для разблакіроўкі</value>
@@ -2299,9 +2299,6 @@
<value>Пасля таго, як ваш ключ паспяхова ўведзены, <value>Пасля таго, як ваш ключ паспяхова ўведзены,
выберыце "Дадаць TOTP" для надзейнага захавання ключа</value> выберыце "Дадаць TOTP" для надзейнага захавання ключа</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Прызначыўшы параметр блакіравання "Ніколі", ваша сховішча будзе даступна кожнаму, хто мае доступ да вашай прылады. Калі вы выкарыстоўваеце гэты параметр, вы павінны быць упэўнены ў тым, што ваша прылада надзейна абаронена.</value> <value>Прызначыўшы параметр блакіравання "Ніколі", ваша сховішча будзе даступна кожнаму, хто мае доступ да вашай прылады. Калі вы выкарыстоўваеце гэты параметр, вы павінны быць упэўнены ў тым, што ваша прылада надзейна абаронена.</value>
</data> </data>
@@ -2452,6 +2449,9 @@
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Выпадкова</value> <value>Выпадкова</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Падлучыцца да гадзінніка</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Апісанне службы спецыяльных магчымасцей</value> <value>Апісанне службы спецыяльных магчымасцей</value>
</data> </data>
@@ -2472,4 +2472,46 @@
{0} {0}
Вы сапраўды хочаце перайсці на гэты ўліковы запіс?</value> Вы сапраўды хочаце перайсці на гэты ўліковы запіс?</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>Упершыню тут?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Атрымаць падказку да асноўнага пароля</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Увайсці як {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Не вы?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Увайсці з асноўным паролем</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Увайсці з іншай прылады</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Ініцыяваны ўваход</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Апавяшчэнне было адпраўлена на вашу прыладу.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Пераканайцеся, што ваша сховішча разблакіравана, а фраза адбітка пальца супадае з іншай прыладай.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Адправіць апавяшчэнне паўторна</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Неабходны іншы варыянт?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Паглядзець усе варыянты ўваходу</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Гэты запыт больш не дзейнічае</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Каб выкарыстоўваць сканер дайце дазвол на выкарыстанне камеры</value>
</data>
</root> </root>

View File

@@ -300,7 +300,7 @@
<comment>The title for the vault page.</comment> <comment>The title for the vault page.</comment>
</data> </data>
<data name="Authenticator" xml:space="preserve"> <data name="Authenticator" xml:space="preserve">
<value>Authenticator</value> <value>Удостоверител</value>
<comment>Authenticator TOTP feature</comment> <comment>Authenticator TOTP feature</comment>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} беше копирано.</value> <value>{0} беше копирано.</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Потвърждаване на пръстовия отпечатък</value> <value>Потвърждаване на пръстовия отпечатък</value>
@@ -2080,7 +2080,7 @@
<value>Това действие е защитено. За да продължите, въведете отново главната си парола, за да потвърдите самоличността си.</value> <value>Това действие е защитено. За да продължите, въведете отново главната си парола, за да потвърдите самоличността си.</value>
</data> </data>
<data name="CaptchaRequired" xml:space="preserve"> <data name="CaptchaRequired" xml:space="preserve">
<value>Captcha required</value> <value>Адресът за hCaptcha е задължителен</value>
</data> </data>
<data name="CaptchaFailed" xml:space="preserve"> <data name="CaptchaFailed" xml:space="preserve">
<value> <value>
@@ -2267,7 +2267,7 @@
<value>Всички</value> <value>Всички</value>
</data> </data>
<data name="Totp" xml:space="preserve"> <data name="Totp" xml:space="preserve">
<value>TOTP</value> <value>Кода за потвърждаване</value>
</data> </data>
<data name="VerificationCodes" xml:space="preserve"> <data name="VerificationCodes" xml:space="preserve">
<value>Кодове за потвърждаване</value> <value>Кодове за потвърждаване</value>
@@ -2291,18 +2291,15 @@
<value>Ръчно въвеждане на кода</value> <value>Ръчно въвеждане на кода</value>
</data> </data>
<data name="AddTotp" xml:space="preserve"> <data name="AddTotp" xml:space="preserve">
<value>Add TOTP</value> <value>Копиране на кода за потвърждаване</value>
</data> </data>
<data name="SetupTotp" xml:space="preserve"> <data name="SetupTotp" xml:space="preserve">
<value>Set up TOTP</value> <value>Копиране на кода за потвърждаване</value>
</data> </data>
<data name="OnceTheKeyIsSuccessfullyEntered" xml:space="preserve"> <data name="OnceTheKeyIsSuccessfullyEntered" xml:space="preserve">
<value>Once the key is successfully entered, <value>Once the key is successfully entered,
select Add TOTP to store the key safely</value> select Add TOTP to store the key safely</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Ако изберете „Никога“ като настройка за заключването, трезорът Ви ще бъде достъпен за всеки, който има досег с устройството. Ако използвате тази настройка, трябва да се уверите, че устройството Ви е удачно защитено.</value> <value>Ако изберете „Никога“ като настройка за заключването, трезорът Ви ще бъде достъпен за всеки, който има досег с устройството. Ако използвате тази настройка, трябва да се уверите, че устройството Ви е удачно защитено.</value>
</data> </data>
@@ -2337,7 +2334,7 @@ select Add TOTP to store the key safely</value>
<value>Време</value> <value>Време</value>
</data> </data>
<data name="Near" xml:space="preserve"> <data name="Near" xml:space="preserve">
<value>Near</value> <value>Близо</value>
</data> </data>
<data name="ConfirmLogIn" xml:space="preserve"> <data name="ConfirmLogIn" xml:space="preserve">
<value>Потвърждаване на вписването</value> <value>Потвърждаване на вписването</value>
@@ -2388,13 +2385,13 @@ select Add TOTP to store the key safely</value>
<value>Тип потребителско име</value> <value>Тип потребителско име</value>
</data> </data>
<data name="PlusAddressedEmail" xml:space="preserve"> <data name="PlusAddressedEmail" xml:space="preserve">
<value>Plus addressed email</value> <value>Адрес на е-поща с плюс</value>
</data> </data>
<data name="CatchAllEmail" xml:space="preserve"> <data name="CatchAllEmail" xml:space="preserve">
<value>Catch-all email</value> <value>Хващаща всичко е-поща</value>
</data> </data>
<data name="ForwardedEmailAlias" xml:space="preserve"> <data name="ForwardedEmailAlias" xml:space="preserve">
<value>Forwarded email alias</value> <value>Псевдоним на препратена е-поща</value>
</data> </data>
<data name="RandomWord" xml:space="preserve"> <data name="RandomWord" xml:space="preserve">
<value>Произволна дума</value> <value>Произволна дума</value>
@@ -2433,7 +2430,7 @@ select Add TOTP to store the key safely</value>
<value>Генериране на потр. име</value> <value>Генериране на потр. име</value>
</data> </data>
<data name="EmailType" xml:space="preserve"> <data name="EmailType" xml:space="preserve">
<value>Email Type</value> <value>Вид е-поща</value>
</data> </data>
<data name="WebsiteRequired" xml:space="preserve"> <data name="WebsiteRequired" xml:space="preserve">
<value>Уеб сайт (задължително)</value> <value>Уеб сайт (задължително)</value>
@@ -2445,14 +2442,17 @@ select Add TOTP to store the key safely</value>
<value>Използвайте възможностите за под-адресиране на е-поща на своя доставчик</value> <value>Използвайте възможностите за под-адресиране на е-поща на своя доставчик</value>
</data> </data>
<data name="CatchAllEmailDescription" xml:space="preserve"> <data name="CatchAllEmailDescription" xml:space="preserve">
<value>Use your domain's configured catch-all inbox.</value> <value>Използвайте конфигурираната входяща кутия за събиране на всичко.</value>
</data> </data>
<data name="ForwardedEmailDescription" xml:space="preserve"> <data name="ForwardedEmailDescription" xml:space="preserve">
<value>Generate an email alias with an external forwarding service.</value> <value>Създайте псевдоним на е-поща с външна услуга за препращане.</value>
</data> </data>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Произволно</value> <value>Произволно</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Свързване към часовник</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Използване на услугата за достъпност</value> <value>Използване на услугата за достъпност</value>
</data> </data>
@@ -2473,4 +2473,46 @@ select Add TOTP to store the key safely</value>
{0} {0}
Искате ли да превключите към тази регистрация?</value> Искате ли да превключите към тази регистрация?</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>За пръв път ли сте тук?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Получете подсказване за главната парола</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Вписване като {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Това не сте Вие?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Вписване с главната парола</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Вписване с друго устройство</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Вписването е стартирано</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Към устройството Ви е изпратено известие.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Уверете се, че трезорът Ви е отключен и че Уникалната фраза съвпада с другото устройство.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Повторно изпращане на известието</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Предпочитате друг вариант?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Вижте всички възможности за вписване</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Тази зявка вече не е приложима</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Разрешете достъпа до камерата, за да използвате скенера</value>
</data>
</root> </root>

View File

@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} copied</value> <value>{0} copied</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Verify fingerprint</value> <value>Verify fingerprint</value>
@@ -1762,7 +1762,7 @@ Scanning will happen automatically.</value>
<value>Syncing vault with pull down gesture.</value> <value>Syncing vault with pull down gesture.</value>
</data> </data>
<data name="LogInSso" xml:space="preserve"> <data name="LogInSso" xml:space="preserve">
<value>Enterprise Single Sign-On</value> <value>Enterprise single sign-on</value>
</data> </data>
<data name="LogInSsoSummary" xml:space="preserve"> <data name="LogInSsoSummary" xml:space="preserve">
<value>Quickly log in using your organization's single sign-on portal. Please enter your organization's identifier to begin.</value> <value>Quickly log in using your organization's single sign-on portal. Please enter your organization's identifier to begin.</value>
@@ -2300,9 +2300,6 @@ Scanning will happen automatically.</value>
<value>Once the key is successfully entered, <value>Once the key is successfully entered,
select Add TOTP to store the key safely</value> select Add TOTP to store the key safely</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Setting your lock options to “Never” keeps your vault available to anyone with access to your device. If you use this option, you should ensure that you keep your device properly protected.</value> <value>Setting your lock options to “Never” keeps your vault available to anyone with access to your device. If you use this option, you should ensure that you keep your device properly protected.</value>
</data> </data>
@@ -2453,6 +2450,9 @@ select Add TOTP to store the key safely</value>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Random</value> <value>Random</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Connect to Watch</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Accessibility Service Disclosure</value> <value>Accessibility Service Disclosure</value>
</data> </data>
@@ -2473,4 +2473,46 @@ select Add TOTP to store the key safely</value>
{0} {0}
Do you want to switch to this account?</value> Do you want to switch to this account?</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>New around here?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Get master password hint</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Logging in as {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Enable camera permission to use the scanner</value>
</data>
</root> </root>

View File

@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} kopirano.</value> <value>{0} kopirano.</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Potvrdi otisak prsta</value> <value>Potvrdi otisak prsta</value>
@@ -1412,7 +1412,7 @@ Scanning will happen automatically.</value>
<value>Nema kolekcija za prikazati.</value> <value>Nema kolekcija za prikazati.</value>
</data> </data>
<data name="MovedItemToOrg" xml:space="preserve"> <data name="MovedItemToOrg" xml:space="preserve">
<value>premješteno u</value> <value>{0} moved to {1}.</value>
<comment>ex: Item moved to Organization.</comment> <comment>ex: Item moved to Organization.</comment>
</data> </data>
<data name="ItemShared" xml:space="preserve"> <data name="ItemShared" xml:space="preserve">
@@ -2299,9 +2299,6 @@ Scanning will happen automatically.</value>
<value>Once the key is successfully entered, <value>Once the key is successfully entered,
select Add TOTP to store the key safely</value> select Add TOTP to store the key safely</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Setting your lock options to “Never” keeps your vault available to anyone with access to your device. If you use this option, you should ensure that you keep your device properly protected.</value> <value>Setting your lock options to “Never” keeps your vault available to anyone with access to your device. If you use this option, you should ensure that you keep your device properly protected.</value>
</data> </data>
@@ -2452,6 +2449,9 @@ select Add TOTP to store the key safely</value>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Random</value> <value>Random</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Connect to Watch</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Accessibility Service Disclosure</value> <value>Accessibility Service Disclosure</value>
</data> </data>
@@ -2472,4 +2472,46 @@ select Add TOTP to store the key safely</value>
{0} {0}
Do you want to switch to this account?</value> Do you want to switch to this account?</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>New around here?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Get master password hint</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Logging in as {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Enable camera permission to use the scanner</value>
</data>
</root> </root>

View File

@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>S'ha copiat '{0}'.</value> <value>S'ha copiat '{0}'.</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Verifica empremta digital</value> <value>Verifica empremta digital</value>
@@ -556,7 +556,7 @@
<value>Temps d'espera de la caixa forta</value> <value>Temps d'espera de la caixa forta</value>
</data> </data>
<data name="VaultTimeoutAction" xml:space="preserve"> <data name="VaultTimeoutAction" xml:space="preserve">
<value>Acció del temps d'espera de la caixa forta</value> <value>Acció quan acabe el temps d'espera de la caixa forta</value>
</data> </data>
<data name="VaultTimeoutLogOutConfirmation" xml:space="preserve"> <data name="VaultTimeoutLogOutConfirmation" xml:space="preserve">
<value>En tancar la sessió s'eliminarà tot l'accés a la vostra caixa forta i es requerirà una autenticació en línia després del període de temps d'espera. Esteu segur que voleu utilitzar aquesta configuració?</value> <value>En tancar la sessió s'eliminarà tot l'accés a la vostra caixa forta i es requerirà una autenticació en línia després del període de temps d'espera. Esteu segur que voleu utilitzar aquesta configuració?</value>
@@ -769,16 +769,16 @@
<value>2. Activeu el commutador i premeu d'acord per acceptar.</value> <value>2. Activeu el commutador i premeu d'acord per acceptar.</value>
</data> </data>
<data name="Disabled" xml:space="preserve"> <data name="Disabled" xml:space="preserve">
<value>Deshabilitat</value> <value>No</value>
</data> </data>
<data name="Enabled" xml:space="preserve"> <data name="Enabled" xml:space="preserve">
<value>Habilitat</value> <value></value>
</data> </data>
<data name="Off" xml:space="preserve"> <data name="Off" xml:space="preserve">
<value>Desactivat</value> <value>No</value>
</data> </data>
<data name="On" xml:space="preserve"> <data name="On" xml:space="preserve">
<value>Activat</value> <value></value>
</data> </data>
<data name="Status" xml:space="preserve"> <data name="Status" xml:space="preserve">
<value>Estat</value> <value>Estat</value>
@@ -1620,13 +1620,13 @@ L'escaneig es farà automàticament.</value>
<value>La vostra sessió ha caducat.</value> <value>La vostra sessió ha caducat.</value>
</data> </data>
<data name="BiometricsDirection" xml:space="preserve"> <data name="BiometricsDirection" xml:space="preserve">
<value>Utilitzeu dades biomètriques per verificar</value> <value>Desbloqueja amb biometria</value>
</data> </data>
<data name="Biometrics" xml:space="preserve"> <data name="Biometrics" xml:space="preserve">
<value>Dades biomètriques</value> <value>Dades biomètriques</value>
</data> </data>
<data name="UseBiometricsToUnlock" xml:space="preserve"> <data name="UseBiometricsToUnlock" xml:space="preserve">
<value>Utilitzeu dades biomètriques per desbloquejar</value> <value>Desbloqueja amb biometria</value>
</data> </data>
<data name="AccessibilityOverlayPermissionAlert" xml:space="preserve"> <data name="AccessibilityOverlayPermissionAlert" xml:space="preserve">
<value>Bitwarden necessita atenció: vegeu "Servei d'accessibilitat d'emplenament automàtic" de la configuració de Bitwarden</value> <value>Bitwarden necessita atenció: vegeu "Servei d'accessibilitat d'emplenament automàtic" de la configuració de Bitwarden</value>
@@ -1828,7 +1828,7 @@ L'escaneig es farà automàticament.</value>
<value>Serveis d'emplenament automàtic</value> <value>Serveis d'emplenament automàtic</value>
</data> </data>
<data name="InlineAutofill" xml:space="preserve"> <data name="InlineAutofill" xml:space="preserve">
<value>Utilitza l'emplenament automàtic en línia</value> <value>Utilitza l'emplenament automàtic integrat</value>
</data> </data>
<data name="InlineAutofillDescription" xml:space="preserve"> <data name="InlineAutofillDescription" xml:space="preserve">
<value>Utilitzeu l'emplenament automàtic en línia si l'IME (teclat) seleccionat l'admet. Si la vostra configuració no és compatible (o aquesta opció està desactivada), s'utilitzarà la superposició d'emplenament automàtic per defecte.</value> <value>Utilitzeu l'emplenament automàtic en línia si l'IME (teclat) seleccionat l'admet. Si la vostra configuració no és compatible (o aquesta opció està desactivada), s'utilitzarà la superposició d'emplenament automàtic per defecte.</value>
@@ -2299,9 +2299,6 @@ L'escaneig es farà automàticament.</value>
<value>Una vegada introduïda la clau correctament, <value>Una vegada introduïda la clau correctament,
seleccioneu Afegeix TOTP per emmagatzemar la clau de manera segura</value> seleccioneu Afegeix TOTP per emmagatzemar la clau de manera segura</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Si configureu les opcions de bloqueig a "Mai", la vostra caixa forta està disponible per a qualsevol persona amb accés al vostre dispositiu. Si utilitzeu aquesta opció, hauríeu d'assegurar-vos de mantenir el vostre dispositiu correctament protegit.</value> <value>Si configureu les opcions de bloqueig a "Mai", la vostra caixa forta està disponible per a qualsevol persona amb accés al vostre dispositiu. Si utilitzeu aquesta opció, hauríeu d'assegurar-vos de mantenir el vostre dispositiu correctament protegit.</value>
</data> </data>
@@ -2452,6 +2449,9 @@ seleccioneu Afegeix TOTP per emmagatzemar la clau de manera segura</value>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Aleatori</value> <value>Aleatori</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Connecta't a Watch</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Divulgació del servei d'accessibilitat</value> <value>Divulgació del servei d'accessibilitat</value>
</data> </data>
@@ -2472,4 +2472,46 @@ seleccioneu Afegeix TOTP per emmagatzemar la clau de manera segura</value>
{0} {0}
Voleu canviar a aquest compte?</value> Voleu canviar a aquest compte?</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>Nou per ací?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Obteniu la pista de la contrasenya mestra</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Connectat com {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>No sou vosaltres?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Inicia sessió amb la contrasenya mestra</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Inicia sessió amb un altre dispositiu</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>S'ha iniciat la sessió</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>S'ha enviat una notificació al vostre dispositiu.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Assegureu-vos que la vostra caixa forta estiga desbloquejada i que la frase d'empremta digital coincidisca amb l'altre dispositiu.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Torna a enviar la notificació</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Necessiteu una altra opció?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Veure totes les opcions d'inici de sessió</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Aquesta sol·licitud ja no és vàlida</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Habilita el permís de la càmera per utilitzar l'escàner</value>
</data>
</root> </root>

View File

@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} bylo zkopírováno.</value> <value>{0} bylo zkopírováno.</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Ověření otisku prstu</value> <value>Ověření otisku prstu</value>
@@ -1457,11 +1457,11 @@ Načtení proběhne automaticky.</value>
<value>Nejsou k dispozici žádné složky k zobrazení.</value> <value>Nejsou k dispozici žádné složky k zobrazení.</value>
</data> </data>
<data name="FingerprintPhrase" xml:space="preserve"> <data name="FingerprintPhrase" xml:space="preserve">
<value>Fráze otisku prstu</value> <value>Fráze otisku účtu</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="YourAccountsFingerprint" xml:space="preserve"> <data name="YourAccountsFingerprint" xml:space="preserve">
<value>Fráze otisku prstu vašeho účtu</value> <value>Fráze otisku vašeho účtu</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">
@@ -2299,9 +2299,6 @@ Načtení proběhne automaticky.</value>
<value>Once the key is successfully entered, <value>Once the key is successfully entered,
select Add TOTP to store the key safely</value> select Add TOTP to store the key safely</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Nastavení zámku na „Nikdy“ ponechá váš trezor k dispozici komukoliv s přístupem k vašemu zařízení. Používáte-li tuto možnost, měli byste zajistit, aby vaše zařízení bylo náležitě chráněno.</value> <value>Nastavení zámku na „Nikdy“ ponechá váš trezor k dispozici komukoliv s přístupem k vašemu zařízení. Používáte-li tuto možnost, měli byste zajistit, aby vaše zařízení bylo náležitě chráněno.</value>
</data> </data>
@@ -2452,6 +2449,9 @@ select Add TOTP to store the key safely</value>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Náhodně</value> <value>Náhodně</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Connect to Watch</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Accessibility Service Disclosure</value> <value>Accessibility Service Disclosure</value>
</data> </data>
@@ -2468,8 +2468,50 @@ select Add TOTP to store the key safely</value>
<value>Požadavek na přihlášení již vypršel.</value> <value>Požadavek na přihlášení již vypršel.</value>
</data> </data>
<data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve"> <data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve">
<value>Login attempt from: <value>Pokus o přihlášení z:
{0} {0}
Do you want to switch to this account?</value> Chcete se přepnout na tento účet?</value>
</data>
<data name="NewAroundHere" xml:space="preserve">
<value>Jste tu noví?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Získat nápovědu pro hlavní heslo</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Přihlášování jako {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Nejste to vy?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Přihlásit se pomocí hlavního hesla</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Přihlásit se pomocí jiného zařízení</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Přihlášení zahájeno</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Na vaše zařízení bylo odesláno oznámení.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Ujistěte se, že je váš trezor odemčen a fráze otisku prstu se shodují s druhým zařízením.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Odeslat oznámení znovu</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Potřebujete jinou možnost?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Zobrazit všechny možnosti přihlášení</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Tento požadavek již není platný</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Enable camera permission to use the scanner</value>
</data> </data>
</root> </root>

View File

@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} kopieret</value> <value>{0} kopieret</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Verificér fingeraftryk</value> <value>Verificér fingeraftryk</value>
@@ -1762,7 +1762,7 @@ Skanning vil ske automatisk.</value>
<value>Synkronisering af boks med træk nedad-gestus.</value> <value>Synkronisering af boks med træk nedad-gestus.</value>
</data> </data>
<data name="LogInSso" xml:space="preserve"> <data name="LogInSso" xml:space="preserve">
<value>Virksomheds Single Sign On</value> <value>Virksomheds Single Sign-On</value>
</data> </data>
<data name="LogInSsoSummary" xml:space="preserve"> <data name="LogInSsoSummary" xml:space="preserve">
<value>Log hurtigt ind vha. din organisations single sign-on portal. Angiv din organisations identifikator for at begynde.</value> <value>Log hurtigt ind vha. din organisations single sign-on portal. Angiv din organisations identifikator for at begynde.</value>
@@ -2299,9 +2299,6 @@ Skanning vil ske automatisk.</value>
<value>Når nøglen er angivet, <value>Når nøglen er angivet,
vælg Tilføj TOTP for at gemme nøglen sikkert</value> vælg Tilføj TOTP for at gemme nøglen sikkert</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Sættes låseindstillingen til “Aldrig”, er din boks tilgængelig for alle med adgang til enheden. Bruges denne mulighed, så vær sikker på, at din enhed er ordentligt beskyttet.</value> <value>Sættes låseindstillingen til “Aldrig”, er din boks tilgængelig for alle med adgang til enheden. Bruges denne mulighed, så vær sikker på, at din enhed er ordentligt beskyttet.</value>
</data> </data>
@@ -2452,6 +2449,9 @@ vælg Tilføj TOTP for at gemme nøglen sikkert</value>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Tilfældig</value> <value>Tilfældig</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Opret forbindelse til Watch</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Oplysninger om tilgængelighedstjeneste</value> <value>Oplysninger om tilgængelighedstjeneste</value>
</data> </data>
@@ -2472,4 +2472,46 @@ vælg Tilføj TOTP for at gemme nøglen sikkert</value>
{0} {0}
Vil du skifte til denne konto?</value> Vil du skifte til denne konto?</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>Ny her?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Få hovedadgangskodetip</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Logger ind som {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Ikke dig?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log ind med hovedadgangskoden</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log ind med en anden enhed</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Indlogning påbegyndt</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>En notifikation er sendt til din enhed.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Sørg for, at din boks er oplåst, samt at Fingeraftrykssætningen på den anden enhed matcher.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Gensend notifikation</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Behov for en anden mulighed?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Vis alle indlogningsmuligheder</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Anmodningen er ikke længere gyldig</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Tildel kameratilladelse for brug af skanneren</value>
</data>
</root> </root>

View File

@@ -229,7 +229,7 @@
<value>Ordner</value> <value>Ordner</value>
</data> </data>
<data name="FolderUpdated" xml:space="preserve"> <data name="FolderUpdated" xml:space="preserve">
<value>Ordner wurde aktualisiert</value> <value>Ordner aktualisiert</value>
</data> </data>
<data name="GoToWebsite" xml:space="preserve"> <data name="GoToWebsite" xml:space="preserve">
<value>Webseite besuchen</value> <value>Webseite besuchen</value>
@@ -342,7 +342,7 @@
<comment>Reveal a hidden value (password).</comment> <comment>Reveal a hidden value (password).</comment>
</data> </data>
<data name="ItemDeleted" xml:space="preserve"> <data name="ItemDeleted" xml:space="preserve">
<value>Eintrag wurde gelöscht</value> <value>Eintrag gelöscht</value>
<comment>Confirmation message after successfully deleting a login.</comment> <comment>Confirmation message after successfully deleting a login.</comment>
</data> </data>
<data name="Submit" xml:space="preserve"> <data name="Submit" xml:space="preserve">
@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} wurde kopiert</value> <value>{0} wurde kopiert</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Fingerabdruck überprüfen</value> <value>Fingerabdruck überprüfen</value>
@@ -416,7 +416,7 @@
<value>Neuer Eintrag</value> <value>Neuer Eintrag</value>
</data> </data>
<data name="AppExtension" xml:space="preserve"> <data name="AppExtension" xml:space="preserve">
<value>App Erweiterung</value> <value>App-Erweiterung</value>
</data> </data>
<data name="AutofillAccessibilityDescription" xml:space="preserve"> <data name="AutofillAccessibilityDescription" xml:space="preserve">
<value>Verwende den Bitwarden Dienst in den Bedienungshilfen, um deine Zugangsdaten in Apps und im Web automatisch ausfüllen zu lassen.</value> <value>Verwende den Bitwarden Dienst in den Bedienungshilfen, um deine Zugangsdaten in Apps und im Web automatisch ausfüllen zu lassen.</value>
@@ -428,7 +428,7 @@
<value>Mehrdeutige Zeichen vermeiden</value> <value>Mehrdeutige Zeichen vermeiden</value>
</data> </data>
<data name="BitwardenAppExtension" xml:space="preserve"> <data name="BitwardenAppExtension" xml:space="preserve">
<value>Bitwarden App Erweiterung</value> <value>Bitwarden App-Erweiterung</value>
</data> </data>
<data name="BitwardenAppExtensionAlert2" xml:space="preserve"> <data name="BitwardenAppExtensionAlert2" xml:space="preserve">
<value>Die einfachste Möglichkeit, neue Anmeldedaten zu Ihrem Tresor hinzuzufügen, ist die Bitwarden App Erweiterung. Erfahren Sie mehr über die Bitwarden App Erweiterung, indem Sie zu dem "Einstellungen"-Bildschirm navigieren.</value> <value>Die einfachste Möglichkeit, neue Anmeldedaten zu Ihrem Tresor hinzuzufügen, ist die Bitwarden App Erweiterung. Erfahren Sie mehr über die Bitwarden App Erweiterung, indem Sie zu dem "Einstellungen"-Bildschirm navigieren.</value>
@@ -477,13 +477,13 @@
<value>Gebe die E-Mail Adresse deines Kontos ein, um den Hinweis für dein Master-Passwort zu erhalten.</value> <value>Gebe die E-Mail Adresse deines Kontos ein, um den Hinweis für dein Master-Passwort zu erhalten.</value>
</data> </data>
<data name="ExntesionReenable" xml:space="preserve"> <data name="ExntesionReenable" xml:space="preserve">
<value>App Erweiterung wieder aktivieren</value> <value>App-Erweiterung wieder aktivieren</value>
</data> </data>
<data name="ExtensionAlmostDone" xml:space="preserve"> <data name="ExtensionAlmostDone" xml:space="preserve">
<value>Fast geschafft!</value> <value>Fast geschafft!</value>
</data> </data>
<data name="ExtensionEnable" xml:space="preserve"> <data name="ExtensionEnable" xml:space="preserve">
<value>App Erweiterung aktivieren</value> <value>App-Erweiterung aktivieren</value>
</data> </data>
<data name="ExtensionInSafari" xml:space="preserve"> <data name="ExtensionInSafari" xml:space="preserve">
<value>In Safari findest du Bitwarden unter dem Teilen-Symbol (Hinweis: scrolle auf der untersten Zeile des Menüs nach rechts).</value> <value>In Safari findest du Bitwarden unter dem Teilen-Symbol (Hinweis: scrolle auf der untersten Zeile des Menüs nach rechts).</value>
@@ -647,7 +647,7 @@
<value>Bist du sicher, dass du das aktuelle Passwort überschreiben möchtest?</value> <value>Bist du sicher, dass du das aktuelle Passwort überschreiben möchtest?</value>
</data> </data>
<data name="PushNotificationAlert" xml:space="preserve"> <data name="PushNotificationAlert" xml:space="preserve">
<value>Bitwarden aktualisiert deinen Tresor mit Pushbenachrichtigungen. Für die bestmögliche Benutzererfahrung tippe im folgenden Dialogfenster auf "Ok", um Pushbenachrichtigungen zu aktivieren.</value> <value>Bitwarden aktualisiert deinen Tresor mit Push-Benachrichtigungen. Für die bestmögliche Benutzererfahrung tippe im folgenden Dialogfenster auf "Ok", um Push-Benachrichtigungen zu aktivieren.</value>
<comment>Push notifications for apple products</comment> <comment>Push notifications for apple products</comment>
</data> </data>
<data name="RateTheApp" xml:space="preserve"> <data name="RateTheApp" xml:space="preserve">
@@ -705,10 +705,10 @@
<comment>What Apple calls their fingerprint reader.</comment> <comment>What Apple calls their fingerprint reader.</comment>
</data> </data>
<data name="TwoStepLogin" xml:space="preserve"> <data name="TwoStepLogin" xml:space="preserve">
<value>Zwei-Faktor Authentifizierung</value> <value>Zwei-Faktor-Authentifizierung</value>
</data> </data>
<data name="TwoStepLoginConfirmation" xml:space="preserve"> <data name="TwoStepLoginConfirmation" xml:space="preserve">
<value>Mit der Zwei-Faktor Authentifizierung wird dein Account zusätzlich abgesichert, da jede Anmeldung durch einen Sicherheitscode, eine Authentifizierungs-App, SMS, einen Anruf oder eine E-Mail verifiziert werden muss. Die Zwei-Faktor Authentifizierung kann im Bitwarden.com Web-Tresor aktiviert werden. Möchtest du die Seite jetzt öffnen?</value> <value>Mit der Zwei-Faktor-Authentifizierung wird dein Account zusätzlich abgesichert, da jede Anmeldung durch einen Sicherheitscode, eine Authentifizierungs-App, SMS, einen Anruf oder eine E-Mail verifiziert werden muss. Die Zwei-Faktor-Authentifizierung kann im Web-Tresor unter bitwarden.com aktiviert werden. Möchtest du die Seite jetzt öffnen?</value>
</data> </data>
<data name="UnlockWith" xml:space="preserve"> <data name="UnlockWith" xml:space="preserve">
<value>Mit {0} entsperren</value> <value>Mit {0} entsperren</value>
@@ -831,7 +831,7 @@
<comment>For 2FA whenever there are no available providers on this device.</comment> <comment>For 2FA whenever there are no available providers on this device.</comment>
</data> </data>
<data name="NoTwoStepAvailable" xml:space="preserve"> <data name="NoTwoStepAvailable" xml:space="preserve">
<value>Dieses Konto hat eine aktive Zwei-Faktor Authentifizierung, allerdings wird keiner der konfigurierten Zwei-Faktor Anbieter von diesem Gerät unterstützt. Bitte nutzen Sie ein unterstütztes Gerät und / oder fügen Sie zusätzliche Anbieter hinzu, die von mehr Geräten unterstützt werden (wie eine Authentifizierungs-App).</value> <value>Dieses Konto hat eine aktive Zwei-Faktor-Authentifizierung, allerdings wird keiner der konfigurierten Zwei-Faktor-Anbieter von diesem Gerät unterstützt. Bitte nutzen Sie ein unterstütztes Gerät und / oder fügen Sie zusätzliche Anbieter hinzu, die von mehr Geräten unterstützt werden (wie eine Authentifizierungs-App).</value>
</data> </data>
<data name="RecoveryCodeTitle" xml:space="preserve"> <data name="RecoveryCodeTitle" xml:space="preserve">
<value>Wiederherstellungscode</value> <value>Wiederherstellungscode</value>
@@ -1726,7 +1726,7 @@ Das Scannen erfolgt automatisch.</value>
<comment>Message shown when interacting with the server</comment> <comment>Message shown when interacting with the server</comment>
</data> </data>
<data name="ItemRestored" xml:space="preserve"> <data name="ItemRestored" xml:space="preserve">
<value>Eintrag wurde wiederhergestellt</value> <value>Eintrag wiederhergestellt</value>
<comment>Confirmation message after successfully restoring a soft-deleted item</comment> <comment>Confirmation message after successfully restoring a soft-deleted item</comment>
</data> </data>
<data name="Trash" xml:space="preserve"> <data name="Trash" xml:space="preserve">
@@ -2298,9 +2298,6 @@ Das Scannen erfolgt automatisch.</value>
<data name="OnceTheKeyIsSuccessfullyEntered" xml:space="preserve"> <data name="OnceTheKeyIsSuccessfullyEntered" xml:space="preserve">
<value>Sobald der Schlüssel erfolgreich eingegeben wurde, wähle TOTP hinzufügen, um den Schlüssel sicher abzuspeichern</value> <value>Sobald der Schlüssel erfolgreich eingegeben wurde, wähle TOTP hinzufügen, um den Schlüssel sicher abzuspeichern</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Wenn du deine Sperroptionen auf „Nie“ einstellst, bleibt dein Tresor für jeden zugänglich, der Zugriff auf dein Gerät hat. Wenn du diese Option verwendest, solltest du sicherstellen, dass du dein Gerät angemessen schützt.</value> <value>Wenn du deine Sperroptionen auf „Nie“ einstellst, bleibt dein Tresor für jeden zugänglich, der Zugriff auf dein Gerät hat. Wenn du diese Option verwendest, solltest du sicherstellen, dass du dein Gerät angemessen schützt.</value>
</data> </data>
@@ -2451,6 +2448,9 @@ Das Scannen erfolgt automatisch.</value>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Zufällig</value> <value>Zufällig</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Mit Uhr verbinden</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Bedienungshilfen Offenlegung</value> <value>Bedienungshilfen Offenlegung</value>
</data> </data>
@@ -2471,4 +2471,46 @@ Das Scannen erfolgt automatisch.</value>
{0} {0}
Möchtest du zu diesem Konto wechseln?</value> Möchtest du zu diesem Konto wechseln?</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>Neu hier?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Hinweis zum Master-Passwort erhalten</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Anmelden als {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Nicht du?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Mit Master-Passwort anmelden</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Mit einem anderen Gerät anmelden</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Anmeldung initiiert</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Eine Benachrichtigung wurde an dein Gerät gesendet.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Bitte stelle sicher, dass dein Tresor entsperrt ist und die Fingerabdruck-Phrase mit dem anderen Gerät übereinstimmt.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Benachrichtigung erneut senden</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Brauchst du eine andere Option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Alle Anmelde-Optionen anzeigen</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Diese Anfrage ist nicht mehr gültig</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Kamerazugriff aktivieren, um den Scanner zu verwenden</value>
</data>
</root> </root>

View File

@@ -377,7 +377,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} έχει αντιγραφεί.</value> <value>{0} έχει αντιγραφεί.</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Επαλήθευση Δακτυλικού Αποτυπώματος</value> <value>Επαλήθευση Δακτυλικού Αποτυπώματος</value>
@@ -2299,9 +2299,6 @@
<value>Μόλις το κλειδί εισαχθεί με επιτυχία, <value>Μόλις το κλειδί εισαχθεί με επιτυχία,
επιλέξτε Προσθήκη TOTP για να αποθηκεύσετε το κλειδί με ασφάλεια</value> επιλέξτε Προσθήκη TOTP για να αποθηκεύσετε το κλειδί με ασφάλεια</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Ρυθμίζοντας τις επιλογές κλειδώματος σε “Ποτέ” κρατά τη κρύπτη σας διαθέσιμη σε οποιονδήποτε με πρόσβαση στη συσκευή σας. Εάν χρησιμοποιείτε αυτήν την επιλογή, θα πρέπει να διασφαλίσετε ότι διατηρείτε τη συσκευή σας σωστά προστατευμένη.</value> <value>Ρυθμίζοντας τις επιλογές κλειδώματος σε “Ποτέ” κρατά τη κρύπτη σας διαθέσιμη σε οποιονδήποτε με πρόσβαση στη συσκευή σας. Εάν χρησιμοποιείτε αυτήν την επιλογή, θα πρέπει να διασφαλίσετε ότι διατηρείτε τη συσκευή σας σωστά προστατευμένη.</value>
</data> </data>
@@ -2452,6 +2449,9 @@
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Τυχαίο</value> <value>Τυχαίο</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Σύνδεση με το ρολόι</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Γνωστοποίηση Υπηρεσίας Προσβασιμότητας</value> <value>Γνωστοποίηση Υπηρεσίας Προσβασιμότητας</value>
</data> </data>
@@ -2472,4 +2472,46 @@
{0} {0}
Do you want to switch to this account?</value> Do you want to switch to this account?</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>New around here?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Get master password hint</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Logging in as {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Enable camera permission to use the scanner</value>
</data>
</root> </root>

View File

@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} copied</value> <value>{0} copied</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Verify fingerprint</value> <value>Verify fingerprint</value>
@@ -471,19 +471,19 @@
<value>Edit item</value> <value>Edit item</value>
</data> </data>
<data name="EnableAutomaticSyncing" xml:space="preserve"> <data name="EnableAutomaticSyncing" xml:space="preserve">
<value>Enable automatic syncing</value> <value>Allow automatic syncing</value>
</data> </data>
<data name="EnterEmailForHint" xml:space="preserve"> <data name="EnterEmailForHint" xml:space="preserve">
<value>Enter your account email address to receive your master password hint.</value> <value>Enter your account email address to receive your master password hint.</value>
</data> </data>
<data name="ExntesionReenable" xml:space="preserve"> <data name="ExntesionReenable" xml:space="preserve">
<value>Re-enable app extension</value> <value>Reactivate app extension</value>
</data> </data>
<data name="ExtensionAlmostDone" xml:space="preserve"> <data name="ExtensionAlmostDone" xml:space="preserve">
<value>Almost done!</value> <value>Almost done!</value>
</data> </data>
<data name="ExtensionEnable" xml:space="preserve"> <data name="ExtensionEnable" xml:space="preserve">
<value>Enable app extension</value> <value>Activate app extension</value>
</data> </data>
<data name="ExtensionInSafari" xml:space="preserve"> <data name="ExtensionInSafari" xml:space="preserve">
<value>In Safari, find Bitwarden using the share icon (hint: scroll to the right on the bottom row of the menu).</value> <value>In Safari, find Bitwarden using the share icon (hint: scroll to the right on the bottom row of the menu).</value>
@@ -604,7 +604,7 @@
<value>Never</value> <value>Never</value>
</data> </data>
<data name="NewItemCreated" xml:space="preserve"> <data name="NewItemCreated" xml:space="preserve">
<value>New item created.</value> <value>Item added</value>
</data> </data>
<data name="NoFavorites" xml:space="preserve"> <data name="NoFavorites" xml:space="preserve">
<value>There are no favourites in your vault.</value> <value>There are no favourites in your vault.</value>
@@ -632,7 +632,7 @@
<value>Other</value> <value>Other</value>
</data> </data>
<data name="PasswordGenerated" xml:space="preserve"> <data name="PasswordGenerated" xml:space="preserve">
<value>Password generated.</value> <value>Password generated</value>
</data> </data>
<data name="PasswordGenerator" xml:space="preserve"> <data name="PasswordGenerator" xml:space="preserve">
<value>Password generator</value> <value>Password generator</value>
@@ -647,7 +647,7 @@
<value>Are you sure you want to overwrite the current password?</value> <value>Are you sure you want to overwrite the current password?</value>
</data> </data>
<data name="PushNotificationAlert" xml:space="preserve"> <data name="PushNotificationAlert" xml:space="preserve">
<value>Bitwarden keeps your vault automatically synced by using push notifications. For the best possible experience, please select "Allow" on the following prompt when asked to enable push notifications.</value> <value>Bitwarden keeps your vault automatically synced by using push notifications. For the best possible experience, please select "Allow" on the following prompt when asked to allow push notifications.</value>
<comment>Push notifications for apple products</comment> <comment>Push notifications for apple products</comment>
</data> </data>
<data name="RateTheApp" xml:space="preserve"> <data name="RateTheApp" xml:space="preserve">
@@ -663,7 +663,7 @@
<value>Re-type master password</value> <value>Re-type master password</value>
</data> </data>
<data name="SearchVault" xml:space="preserve"> <data name="SearchVault" xml:space="preserve">
<value>Search Vault</value> <value>Search vault</value>
</data> </data>
<data name="Security" xml:space="preserve"> <data name="Security" xml:space="preserve">
<value>Security</value> <value>Security</value>
@@ -681,7 +681,7 @@
<value>Item information</value> <value>Item information</value>
</data> </data>
<data name="ItemUpdated" xml:space="preserve"> <data name="ItemUpdated" xml:space="preserve">
<value>Item updated.</value> <value>Item saved</value>
</data> </data>
<data name="Submitting" xml:space="preserve"> <data name="Submitting" xml:space="preserve">
<value>Submitting...</value> <value>Submitting...</value>
@@ -692,10 +692,10 @@
<comment>Message shown when interacting with the server</comment> <comment>Message shown when interacting with the server</comment>
</data> </data>
<data name="SyncingComplete" xml:space="preserve"> <data name="SyncingComplete" xml:space="preserve">
<value>Syncing complete.</value> <value>Syncing complete</value>
</data> </data>
<data name="SyncingFailed" xml:space="preserve"> <data name="SyncingFailed" xml:space="preserve">
<value>Syncing failed.</value> <value>Syncing failed</value>
</data> </data>
<data name="SyncVaultNow" xml:space="preserve"> <data name="SyncVaultNow" xml:space="preserve">
<value>Sync vault now</value> <value>Sync vault now</value>
@@ -708,7 +708,7 @@
<value>Two-step login</value> <value>Two-step login</value>
</data> </data>
<data name="TwoStepLoginConfirmation" xml:space="preserve"> <data name="TwoStepLoginConfirmation" xml:space="preserve">
<value>Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?</value> <value>Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be set up on the bitwarden.com web vault. Do you want to visit the website now?</value>
</data> </data>
<data name="UnlockWith" xml:space="preserve"> <data name="UnlockWith" xml:space="preserve">
<value>Unlock with {0}</value> <value>Unlock with {0}</value>
@@ -831,7 +831,7 @@
<comment>For 2FA whenever there are no available providers on this device.</comment> <comment>For 2FA whenever there are no available providers on this device.</comment>
</data> </data>
<data name="NoTwoStepAvailable" xml:space="preserve"> <data name="NoTwoStepAvailable" xml:space="preserve">
<value>This account has two-step login enabled. However, none of the configured two-step providers are supported on this device. Please use a supported device and/or add additional providers that are better supported across devices (such as an authenticator app).</value> <value>This account has two-step login set up, however, none of the configured two-step providers are supported on this device. Please use a supported device and/or add additional providers that are better supported across devices (such as an authenticator app).</value>
</data> </data>
<data name="RecoveryCodeTitle" xml:space="preserve"> <data name="RecoveryCodeTitle" xml:space="preserve">
<value>Recovery code</value> <value>Recovery code</value>
@@ -856,7 +856,7 @@
<comment>For 2FA</comment> <comment>For 2FA</comment>
</data> </data>
<data name="VerificationEmailSent" xml:space="preserve"> <data name="VerificationEmailSent" xml:space="preserve">
<value>Verification email sent.</value> <value>Verification email sent</value>
<comment>For 2FA</comment> <comment>For 2FA</comment>
</data> </data>
<data name="YubiKeyInstruction" xml:space="preserve"> <data name="YubiKeyInstruction" xml:space="preserve">
@@ -1080,7 +1080,7 @@ Scanning will happen automatically.</value>
<value>Last name</value> <value>Last name</value>
</data> </data>
<data name="FullName" xml:space="preserve"> <data name="FullName" xml:space="preserve">
<value>Full Name</value> <value>Full name</value>
</data> </data>
<data name="LicenseNumber" xml:space="preserve"> <data name="LicenseNumber" xml:space="preserve">
<value>Licence number</value> <value>Licence number</value>
@@ -1301,7 +1301,7 @@ Scanning will happen automatically.</value>
<value>Access your vault directly from your keyboard to quickly auto-fill passwords.</value> <value>Access your vault directly from your keyboard to quickly auto-fill passwords.</value>
</data> </data>
<data name="AutofillTurnOn" xml:space="preserve"> <data name="AutofillTurnOn" xml:space="preserve">
<value>To enable password auto-fill on your device, follow these instructions:</value> <value>To set up password auto-fill on your device, follow these instructions:</value>
</data> </data>
<data name="AutofillTurnOn1" xml:space="preserve"> <data name="AutofillTurnOn1" xml:space="preserve">
<value>1. Go to the iOS "Settings" app</value> <value>1. Go to the iOS "Settings" app</value>
@@ -1381,10 +1381,10 @@ Scanning will happen automatically.</value>
<value>Search collection</value> <value>Search collection</value>
</data> </data>
<data name="SearchFileSends" xml:space="preserve"> <data name="SearchFileSends" xml:space="preserve">
<value>Search File Sends</value> <value>Search file Sends</value>
</data> </data>
<data name="SearchTextSends" xml:space="preserve"> <data name="SearchTextSends" xml:space="preserve">
<value>Search Text Sends</value> <value>Search text Sends</value>
</data> </data>
<data name="SearchGroup" xml:space="preserve"> <data name="SearchGroup" xml:space="preserve">
<value>Search {0}</value> <value>Search {0}</value>
@@ -1480,7 +1480,7 @@ Scanning will happen automatically.</value>
<value>Unlock</value> <value>Unlock</value>
</data> </data>
<data name="UnlockVault" xml:space="preserve"> <data name="UnlockVault" xml:space="preserve">
<value>Unlock Vault</value> <value>Unlock vault</value>
</data> </data>
<data name="ThirtyMinutes" xml:space="preserve"> <data name="ThirtyMinutes" xml:space="preserve">
<value>30 minutes</value> <value>30 minutes</value>
@@ -1553,10 +1553,10 @@ Scanning will happen automatically.</value>
<value>Default dark theme</value> <value>Default dark theme</value>
</data> </data>
<data name="DefaultDarkThemeDescription" xml:space="preserve"> <data name="DefaultDarkThemeDescription" xml:space="preserve">
<value>Choose the dark theme to use when using Default (System) theme while your device's dark mode is enabled.</value> <value>Choose the dark theme to use when using Default (System) theme while your device's dark mode is in use.</value>
</data> </data>
<data name="CopyNotes" xml:space="preserve"> <data name="CopyNotes" xml:space="preserve">
<value>Copy Note</value> <value>Copy note</value>
</data> </data>
<data name="Exit" xml:space="preserve"> <data name="Exit" xml:space="preserve">
<value>Exit</value> <value>Exit</value>
@@ -1595,7 +1595,7 @@ Scanning will happen automatically.</value>
<value>On app restart</value> <value>On app restart</value>
</data> </data>
<data name="AutofillServiceNotEnabled" xml:space="preserve"> <data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>Auto-fill makes it easy to securely access your Bitwarden vault from other websites and apps. It looks like you have not enabled an auto-fill service for Bitwarden. Enable auto-fill for Bitwarden from the "Settings" screen.</value> <value>Auto-fill makes it easy to securely access your Bitwarden vault from other websites and apps. It looks like you have not set up an auto-fill service for Bitwarden. Set up auto-fill for Bitwarden from the "Settings" screen.</value>
</data> </data>
<data name="ThemeAppliedOnRestart" xml:space="preserve"> <data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Your theme changes will apply when the app is restarted.</value> <value>Your theme changes will apply when the app is restarted.</value>
@@ -1629,10 +1629,10 @@ Scanning will happen automatically.</value>
<value>Use biometrics to unlock</value> <value>Use biometrics to unlock</value>
</data> </data>
<data name="AccessibilityOverlayPermissionAlert" xml:space="preserve"> <data name="AccessibilityOverlayPermissionAlert" xml:space="preserve">
<value>Bitwarden needs attention - See "Auto-fill Accessibility Service" from Bitwarden Settings</value> <value>Bitwarden needs attention - See "Auto-fill Accessibility Service" from Bitwarden settings</value>
</data> </data>
<data name="BitwardenAutofillServiceOverlayPermission" xml:space="preserve"> <data name="BitwardenAutofillServiceOverlayPermission" xml:space="preserve">
<value>3. On the Android App Settings screen for Bitwarden, go to the "Display over other apps" options (under Advanced) and tap the toggle to enable overlay support.</value> <value>3. On the Android App Settings screen for Bitwarden, go to the "Display over other apps" options (under Advanced) and tap the toggle to allow overlay support.</value>
</data> </data>
<data name="OverlayPermission" xml:space="preserve"> <data name="OverlayPermission" xml:space="preserve">
<value>Permission</value> <value>Permission</value>
@@ -1659,7 +1659,7 @@ Scanning will happen automatically.</value>
<value>Send a verification code to your email</value> <value>Send a verification code to your email</value>
</data> </data>
<data name="CodeSent" xml:space="preserve"> <data name="CodeSent" xml:space="preserve">
<value>Code Sent!</value> <value>Code sent!</value>
</data> </data>
<data name="ConfirmYourIdentity" xml:space="preserve"> <data name="ConfirmYourIdentity" xml:space="preserve">
<value>Confirm your identity to continue.</value> <value>Confirm your identity to continue.</value>
@@ -1674,7 +1674,7 @@ Scanning will happen automatically.</value>
<value>Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account.</value> <value>Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account.</value>
</data> </data>
<data name="ExportVaultConfirmationTitle" xml:space="preserve"> <data name="ExportVaultConfirmationTitle" xml:space="preserve">
<value>Confirm Vault Export</value> <value>Confirm vault export</value>
<comment>Title for the alert to confirm vault exports.</comment> <comment>Title for the alert to confirm vault exports.</comment>
</data> </data>
<data name="Warning" xml:space="preserve"> <data name="Warning" xml:space="preserve">
@@ -1704,7 +1704,7 @@ Scanning will happen automatically.</value>
<value>Attachment saved successfully</value> <value>Attachment saved successfully</value>
</data> </data>
<data name="AutofillTileAccessibilityRequired" xml:space="preserve"> <data name="AutofillTileAccessibilityRequired" xml:space="preserve">
<value>Please enable "Auto-fill accessibility service" from Bitwarden settings to use the auto-fill tile.</value> <value>Please turn on "Auto-fill Accessibility Service" from Bitwarden Settings to use the Auto-fill tile.</value>
</data> </data>
<data name="AutofillTileUriNotFound" xml:space="preserve"> <data name="AutofillTileUriNotFound" xml:space="preserve">
<value>No password fields detected</value> <value>No password fields detected</value>
@@ -1726,7 +1726,7 @@ Scanning will happen automatically.</value>
<comment>Message shown when interacting with the server</comment> <comment>Message shown when interacting with the server</comment>
</data> </data>
<data name="ItemRestored" xml:space="preserve"> <data name="ItemRestored" xml:space="preserve">
<value>Item has been restored.</value> <value>Item restored</value>
<comment>Confirmation message after successfully restoring a soft-deleted item</comment> <comment>Confirmation message after successfully restoring a soft-deleted item</comment>
</data> </data>
<data name="Trash" xml:space="preserve"> <data name="Trash" xml:space="preserve">
@@ -1756,7 +1756,7 @@ Scanning will happen automatically.</value>
<value>Biometric unlock for autofill disabled pending verification of master password.</value> <value>Biometric unlock for autofill disabled pending verification of master password.</value>
</data> </data>
<data name="EnableSyncOnRefresh" xml:space="preserve"> <data name="EnableSyncOnRefresh" xml:space="preserve">
<value>Enable sync on refresh</value> <value>Allow sync on refresh</value>
</data> </data>
<data name="EnableSyncOnRefreshDescription" xml:space="preserve"> <data name="EnableSyncOnRefreshDescription" xml:space="preserve">
<value>Syncing vault with pull down gesture.</value> <value>Syncing vault with pull down gesture.</value>
@@ -1822,8 +1822,7 @@ Scanning will happen automatically.</value>
<value>Privacy policy</value> <value>Privacy policy</value>
</data> </data>
<data name="AccessibilityDrawOverPermissionAlert" xml:space="preserve"> <data name="AccessibilityDrawOverPermissionAlert" xml:space="preserve">
<value>Bitwarden needs attention - Enable "Draw-Over" in "Auto-fill Services" from Bitwarden Settings <value>Bitwarden needs attention - Turn on "Draw-Over" in "Auto-fill Services" from Bitwarden Settings</value>
</value>
</data> </data>
<data name="AutofillServices" xml:space="preserve"> <data name="AutofillServices" xml:space="preserve">
<value>Auto-fill services</value> <value>Auto-fill services</value>
@@ -1832,45 +1831,37 @@ Scanning will happen automatically.</value>
<value>Use inline autofill</value> <value>Use inline autofill</value>
</data> </data>
<data name="InlineAutofillDescription" xml:space="preserve"> <data name="InlineAutofillDescription" xml:space="preserve">
<value>Use inline autofill if your selected IME (keyboard) supports it. If your configuration is not supported (or this option is disabled), the default Autofill overlay will be used. <value>Use inline autofill if your selected IME (keyboard) supports it. If your configuration is not supported (or this option is turned off), the default Autofill overlay will be used.</value>
</value>
</data> </data>
<data name="Accessibility" xml:space="preserve"> <data name="Accessibility" xml:space="preserve">
<value>Use accessibility</value> <value>Use accessibility</value>
</data> </data>
<data name="AccessibilityDescription" xml:space="preserve"> <data name="AccessibilityDescription" xml:space="preserve">
<value>Use the Bitwarden Accessibility Service to auto-fill your logins across apps and the web. When enabled, we'll display a popup when login fields are selected. <value>Use the Bitwarden Accessibility Service to auto-fill your logins across apps and the web. When set up, we'll display a popup when login fields are selected.</value>
</value>
</data> </data>
<data name="AccessibilityDescription2" xml:space="preserve"> <data name="AccessibilityDescription2" xml:space="preserve">
<value>Use the Bitwarden Accessibility Service to auto-fill your logins across apps and the web. (Requires Draw-Over to be enabled as well) <value>Use the Bitwarden Accessibility Service to auto-fill your logins across apps and the web. (Requires Draw-Over to be turned on as well)</value>
</value>
</data> </data>
<data name="AccessibilityDescription3" xml:space="preserve"> <data name="AccessibilityDescription3" xml:space="preserve">
<value>Use the Bitwarden Accessibility Service to use the Autofill Quick-Action Tile, and/or show a popup using Draw-Over (if enabled). <value>Use the Bitwarden Accessibility Service to use the Autofill Quick-Action Tile, and/or show a popup using Draw-Over (if turned on).</value>
</value>
</data> </data>
<data name="AccessibilityDescription4" xml:space="preserve"> <data name="AccessibilityDescription4" xml:space="preserve">
<value>Required to use the Autofill Quick-Action Tile, or to augment the Autofill Service by using Draw-Over (if enabled). <value>Required to use the Autofill Quick-Action Tile, or to augment the Autofill Service by using Draw-Over (if turned on).</value>
</value>
</data> </data>
<data name="DrawOver" xml:space="preserve"> <data name="DrawOver" xml:space="preserve">
<value>Use draw-over</value> <value>Use draw-over</value>
</data> </data>
<data name="DrawOverDescription" xml:space="preserve"> <data name="DrawOverDescription" xml:space="preserve">
<value>When enabled, allows the Bitwarden Accessibility Service to display a popup when login fields are selected. <value>Allows the Bitwarden Accessibility Service to display a popup when login fields are selected.</value>
</value>
</data> </data>
<data name="DrawOverDescription2" xml:space="preserve"> <data name="DrawOverDescription2" xml:space="preserve">
<value>If enabled, the Bitwarden Accessibility Service will display a popup when login fields are selected to assist with auto-filling your logins. <value>If turned on, the Bitwarden Accessibility Service will display a popup when login fields are selected to assist with auto-filling your logins.</value>
</value>
</data> </data>
<data name="DrawOverDescription3" xml:space="preserve"> <data name="DrawOverDescription3" xml:space="preserve">
<value>If enabled, accessibility will show a popup to augment the Autofill Service for older apps that don't support the Android Autofill Framework. <value>If turned on, accessibility will show a popup to augment the Autofill Service for older apps that don't support the Android Autofill Framework.</value>
</value>
</data> </data>
<data name="PersonalOwnershipSubmitError" xml:space="preserve"> <data name="PersonalOwnershipSubmitError" xml:space="preserve">
<value>Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organisation and choose from available Collections.</value> <value>Due to an enterprise policy, you are restricted from saving items to your individual vault. Change the ownership option to an organisation and choose from available collections.</value>
</data> </data>
<data name="PersonalOwnershipPolicyInEffect" xml:space="preserve"> <data name="PersonalOwnershipPolicyInEffect" xml:space="preserve">
<value>An organisation policy is affecting your ownership options.</value> <value>An organisation policy is affecting your ownership options.</value>
@@ -1923,10 +1914,10 @@ Scanning will happen automatically.</value>
<value>Text type is not selected, tap to select.</value> <value>Text type is not selected, tap to select.</value>
</data> </data>
<data name="DeletionDate" xml:space="preserve"> <data name="DeletionDate" xml:space="preserve">
<value>Deletion Date</value> <value>Deletion date</value>
</data> </data>
<data name="DeletionTime" xml:space="preserve"> <data name="DeletionTime" xml:space="preserve">
<value>Deletion Time</value> <value>Deletion time</value>
</data> </data>
<data name="DeletionDateInfo" xml:space="preserve"> <data name="DeletionDateInfo" xml:space="preserve">
<value>The Send will be permanently deleted on the specified date and time.</value> <value>The Send will be permanently deleted on the specified date and time.</value>
@@ -1936,10 +1927,10 @@ Scanning will happen automatically.</value>
<value>Pending deletion</value> <value>Pending deletion</value>
</data> </data>
<data name="ExpirationDate" xml:space="preserve"> <data name="ExpirationDate" xml:space="preserve">
<value>Expiration Date</value> <value>Expiration date</value>
</data> </data>
<data name="ExpirationTime" xml:space="preserve"> <data name="ExpirationTime" xml:space="preserve">
<value>Expiration Time</value> <value>Expiration time</value>
</data> </data>
<data name="ExpirationDateInfo" xml:space="preserve"> <data name="ExpirationDateInfo" xml:space="preserve">
<value>If set, access to this Send will expire on the specified date and time.</value> <value>If set, access to this Send will expire on the specified date and time.</value>
@@ -1949,7 +1940,7 @@ Scanning will happen automatically.</value>
<value>Expired</value> <value>Expired</value>
</data> </data>
<data name="MaximumAccessCount" xml:space="preserve"> <data name="MaximumAccessCount" xml:space="preserve">
<value>Maximum Access Count</value> <value>Maximum access count</value>
</data> </data>
<data name="MaximumAccessCountInfo" xml:space="preserve"> <data name="MaximumAccessCountInfo" xml:space="preserve">
<value>If set, users will no longer be able to access this send once the maximum access count is reached.</value> <value>If set, users will no longer be able to access this send once the maximum access count is reached.</value>
@@ -1959,17 +1950,17 @@ Scanning will happen automatically.</value>
<value>Max access count reached</value> <value>Max access count reached</value>
</data> </data>
<data name="CurrentAccessCount" xml:space="preserve"> <data name="CurrentAccessCount" xml:space="preserve">
<value>Current Access Count</value> <value>Current access count</value>
</data> </data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>New Password</value> <value>New password</value>
</data> </data>
<data name="PasswordInfo" xml:space="preserve"> <data name="PasswordInfo" xml:space="preserve">
<value>Optionally require a password for users to access this Send.</value> <value>Optionally require a password for users to access this Send.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="RemovePassword" xml:space="preserve"> <data name="RemovePassword" xml:space="preserve">
<value>Remove Password</value> <value>Remove password</value>
</data> </data>
<data name="AreYouSureRemoveSendPassword" xml:space="preserve"> <data name="AreYouSureRemoveSendPassword" xml:space="preserve">
<value>Are you sure you want to remove the password?</value> <value>Are you sure you want to remove the password?</value>
@@ -1985,7 +1976,7 @@ Scanning will happen automatically.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="DisableSend" xml:space="preserve"> <data name="DisableSend" xml:space="preserve">
<value>Disable this Send so that no one can access it</value> <value>Deactivate this Send so that no one can access it</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="NoSends" xml:space="preserve"> <data name="NoSends" xml:space="preserve">
@@ -1997,10 +1988,10 @@ Scanning will happen automatically.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="CopyLink" xml:space="preserve"> <data name="CopyLink" xml:space="preserve">
<value>Copy Link</value> <value>Copy link</value>
</data> </data>
<data name="ShareLink" xml:space="preserve"> <data name="ShareLink" xml:space="preserve">
<value>Share Link</value> <value>Share link</value>
</data> </data>
<data name="SendLink" xml:space="preserve"> <data name="SendLink" xml:space="preserve">
<value>Send link</value> <value>Send link</value>
@@ -2015,7 +2006,7 @@ Scanning will happen automatically.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="AddSend" xml:space="preserve"> <data name="AddSend" xml:space="preserve">
<value>Add Send</value> <value>New Send</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="AreYouSureDeleteSend" xml:space="preserve"> <data name="AreYouSureDeleteSend" xml:space="preserve">
@@ -2023,15 +2014,15 @@ Scanning will happen automatically.</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="SendDeleted" xml:space="preserve"> <data name="SendDeleted" xml:space="preserve">
<value>Send has been deleted.</value> <value>Send deleted</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="SendUpdated" xml:space="preserve"> <data name="SendUpdated" xml:space="preserve">
<value>Send updated.</value> <value>Send saved</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="NewSendCreated" xml:space="preserve"> <data name="NewSendCreated" xml:space="preserve">
<value>New send created.</value> <value>Send created</value>
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment> <comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
</data> </data>
<data name="OneDay" xml:space="preserve"> <data name="OneDay" xml:space="preserve">
@@ -2089,37 +2080,37 @@ Scanning will happen automatically.</value>
<value>This action is protected, to continue please re-enter your master password to verify your identity.</value> <value>This action is protected, to continue please re-enter your master password to verify your identity.</value>
</data> </data>
<data name="CaptchaRequired" xml:space="preserve"> <data name="CaptchaRequired" xml:space="preserve">
<value>Captcha Required</value> <value>Captcha required</value>
</data> </data>
<data name="CaptchaFailed" xml:space="preserve"> <data name="CaptchaFailed" xml:space="preserve">
<value>Captcha Failed. Please try again.</value> <value>Captcha failed. Please try again.</value>
</data> </data>
<data name="UpdatedMasterPassword" xml:space="preserve"> <data name="UpdatedMasterPassword" xml:space="preserve">
<value>Updated Master Password</value> <value>Updated master password</value>
</data> </data>
<data name="UpdateMasterPassword" xml:space="preserve"> <data name="UpdateMasterPassword" xml:space="preserve">
<value>Update Master Password</value> <value>Update master password</value>
</data> </data>
<data name="UpdateMasterPasswordWarning" xml:space="preserve"> <data name="UpdateMasterPasswordWarning" xml:space="preserve">
<value>Your Master Password was recently changed by an administrator in your organisation. In order to access the vault, you must update your Master Password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour.</value> <value>Your master password was recently changed by an administrator in your organisation. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour.</value>
</data> </data>
<data name="UpdatingPassword" xml:space="preserve"> <data name="UpdatingPassword" xml:space="preserve">
<value>Updating Password</value> <value>Updating password</value>
</data> </data>
<data name="UpdatePasswordError" xml:space="preserve"> <data name="UpdatePasswordError" xml:space="preserve">
<value>Currently unable to update password</value> <value>Currently unable to update password</value>
</data> </data>
<data name="RemoveMasterPassword" xml:space="preserve"> <data name="RemoveMasterPassword" xml:space="preserve">
<value>Remove Master Password</value> <value>Remove master password</value>
</data> </data>
<data name="RemoveMasterPasswordWarning" xml:space="preserve"> <data name="RemoveMasterPasswordWarning" xml:space="preserve">
<value>{0} is using SSO with customer-managed encryption. Continuing will remove your Master Password from your account and require SSO to login.</value> <value>{0} is using SSO with customer-managed encryption. Continuing will remove your master password from your account and require SSO to login.</value>
</data> </data>
<data name="RemoveMasterPasswordWarning2" xml:space="preserve"> <data name="RemoveMasterPasswordWarning2" xml:space="preserve">
<value>If you do not want to remove your Master Password, you may leave this organisation.</value> <value>If you do not want to remove your master password, you may leave this organisation.</value>
</data> </data>
<data name="LeaveOrganization" xml:space="preserve"> <data name="LeaveOrganization" xml:space="preserve">
<value>Leave Organisation</value> <value>Leave organisation</value>
</data> </data>
<data name="LeaveOrganizationName" xml:space="preserve"> <data name="LeaveOrganizationName" xml:space="preserve">
<value>Leave {0}?</value> <value>Leave {0}?</value>
@@ -2128,7 +2119,7 @@ Scanning will happen automatically.</value>
<value>FIDO2 WebAuthn</value> <value>FIDO2 WebAuthn</value>
</data> </data>
<data name="Fido2Instruction" xml:space="preserve"> <data name="Fido2Instruction" xml:space="preserve">
<value>To continue, have your FIDO2 WebAuthn enabled security key ready, then follow the instructions after clicking 'Authenticate WebAuthn' on the next screen.</value> <value>To continue, have your FIDO2 WebAuthn compatible security key ready, then follow the instructions after clicking 'Authenticate WebAuthn' on the next screen.</value>
</data> </data>
<data name="Fido2Desc" xml:space="preserve"> <data name="Fido2Desc" xml:space="preserve">
<value>Authentication using FIDO2 WebAuthn, you can authenticate using an external security key.</value> <value>Authentication using FIDO2 WebAuthn, you can authenticate using an external security key.</value>
@@ -2137,7 +2128,7 @@ Scanning will happen automatically.</value>
<value>Authenticate WebAuthn</value> <value>Authenticate WebAuthn</value>
</data> </data>
<data name="Fido2ReturnToApp" xml:space="preserve"> <data name="Fido2ReturnToApp" xml:space="preserve">
<value>Return to App</value> <value>Return to app</value>
</data> </data>
<data name="Fido2CheckBrowser" xml:space="preserve"> <data name="Fido2CheckBrowser" xml:space="preserve">
<value>Please make sure your default browser supports WebAuthn and try again.</value> <value>Please make sure your default browser supports WebAuthn and try again.</value>
@@ -2146,16 +2137,16 @@ Scanning will happen automatically.</value>
<value>This organisation has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organisation administrators to change your master password.</value> <value>This organisation has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organisation administrators to change your master password.</value>
</data> </data>
<data name="VaultTimeoutPolicyInEffect" xml:space="preserve"> <data name="VaultTimeoutPolicyInEffect" xml:space="preserve">
<value>Your organisation policies are affecting your vault timeout. Maximum allowed Vault Timeout is {0} hour(s) and {1} minute(s)</value> <value>Your organisation policies are affecting your vault timeout. Maximum allowed vault timeout is {0} hour(s) and {1} minute(s)</value>
</data> </data>
<data name="VaultTimeoutToLarge" xml:space="preserve"> <data name="VaultTimeoutToLarge" xml:space="preserve">
<value>Your vault timeout exceeds the restrictions set by your organisation.</value> <value>Your vault timeout exceeds the restrictions set by your organisation.</value>
</data> </data>
<data name="DisablePersonalVaultExportPolicyInEffect"> <data name="DisablePersonalVaultExportPolicyInEffect">
<value>One or more organisation policies prevents your from exporting your personal vault.</value> <value>One or more organisation policies prevents your from exporting your individual vault.</value>
</data> </data>
<data name="AddAccount" xml:space="preserve"> <data name="AddAccount" xml:space="preserve">
<value>Add Account</value> <value>Add account</value>
</data> </data>
<data name="AccountUnlocked" xml:space="preserve"> <data name="AccountUnlocked" xml:space="preserve">
<value>Unlocked</value> <value>Unlocked</value>
@@ -2164,13 +2155,13 @@ Scanning will happen automatically.</value>
<value>Locked</value> <value>Locked</value>
</data> </data>
<data name="AccountLoggedOut" xml:space="preserve"> <data name="AccountLoggedOut" xml:space="preserve">
<value>Logged Out</value> <value>Logged out</value>
</data> </data>
<data name="AccountSwitchedAutomatically" xml:space="preserve"> <data name="AccountSwitchedAutomatically" xml:space="preserve">
<value>Switched to next available account</value> <value>Switched to next available account</value>
</data> </data>
<data name="AccountLockedSuccessfully" xml:space="preserve"> <data name="AccountLockedSuccessfully" xml:space="preserve">
<value>Account Locked</value> <value>Account locked</value>
</data> </data>
<data name="AccountLoggedOutSuccessfully" xml:space="preserve"> <data name="AccountLoggedOutSuccessfully" xml:space="preserve">
<value>Account logged out successfully</value> <value>Account logged out successfully</value>
@@ -2194,13 +2185,13 @@ Scanning will happen automatically.</value>
<value>Your account has been permanently deleted</value> <value>Your account has been permanently deleted</value>
</data> </data>
<data name="InvalidVerificationCode" xml:space="preserve"> <data name="InvalidVerificationCode" xml:space="preserve">
<value>Invalid Verification Code.</value> <value>Invalid verification code</value>
</data> </data>
<data name="RequestOTP" xml:space="preserve"> <data name="RequestOTP" xml:space="preserve">
<value>Request one-time password</value> <value>Request one-time password</value>
</data> </data>
<data name="SendCode" xml:space="preserve"> <data name="SendCode" xml:space="preserve">
<value>Send Code</value> <value>Send code</value>
</data> </data>
<data name="Sending" xml:space="preserve"> <data name="Sending" xml:space="preserve">
<value>Sending</value> <value>Sending</value>
@@ -2215,7 +2206,7 @@ Scanning will happen automatically.</value>
<value>Verifying</value> <value>Verifying</value>
</data> </data>
<data name="ResendCode" xml:space="preserve"> <data name="ResendCode" xml:space="preserve">
<value>Resend Code</value> <value>Resend code</value>
</data> </data>
<data name="AVerificationCodeWasSentToYourEmail" xml:space="preserve"> <data name="AVerificationCodeWasSentToYourEmail" xml:space="preserve">
<value>A verification code was sent to your email</value> <value>A verification code was sent to your email</value>
@@ -2248,7 +2239,7 @@ Scanning will happen automatically.</value>
<value>Numbers (0 to 9)</value> <value>Numbers (0 to 9)</value>
</data> </data>
<data name="SpecialCharacters" xml:space="preserve"> <data name="SpecialCharacters" xml:space="preserve">
<value>Special Characters (!@#$%^&amp;*)</value> <value>Special characters (!@#$%^&amp;*)</value>
</data> </data>
<data name="TapToGoBack" xml:space="preserve"> <data name="TapToGoBack" xml:space="preserve">
<value>Tap to go back</value> <value>Tap to go back</value>
@@ -2263,7 +2254,7 @@ Scanning will happen automatically.</value>
<value>Filter items by vault</value> <value>Filter items by vault</value>
</data> </data>
<data name="AllVaults" xml:space="preserve"> <data name="AllVaults" xml:space="preserve">
<value>All Vaults</value> <value>All vaults</value>
</data> </data>
<data name="Vaults" xml:space="preserve"> <data name="Vaults" xml:space="preserve">
<value>Vaults</value> <value>Vaults</value>
@@ -2278,7 +2269,7 @@ Scanning will happen automatically.</value>
<value>TOTP</value> <value>TOTP</value>
</data> </data>
<data name="VerificationCodes" xml:space="preserve"> <data name="VerificationCodes" xml:space="preserve">
<value>Verification Codes</value> <value>Verification codes</value>
</data> </data>
<data name="PremiumSubscriptionRequired" xml:space="preserve"> <data name="PremiumSubscriptionRequired" xml:space="preserve">
<value>Premium subscription required</value> <value>Premium subscription required</value>
@@ -2293,10 +2284,10 @@ Scanning will happen automatically.</value>
<value>Cannot scan QR Code? </value> <value>Cannot scan QR Code? </value>
</data> </data>
<data name="AuthenticatorKeyScanner" xml:space="preserve"> <data name="AuthenticatorKeyScanner" xml:space="preserve">
<value>Authenticator Key</value> <value>Authenticator key</value>
</data> </data>
<data name="EnterKeyManually" xml:space="preserve"> <data name="EnterKeyManually" xml:space="preserve">
<value>Enter Key Manually</value> <value>Enter key manually</value>
</data> </data>
<data name="AddTotp" xml:space="preserve"> <data name="AddTotp" xml:space="preserve">
<value>Add TOTP</value> <value>Add TOTP</value>
@@ -2308,9 +2299,6 @@ Scanning will happen automatically.</value>
<value>Once the key is successfully entered, <value>Once the key is successfully entered,
select Add TOTP to store the key safely</value> select Add TOTP to store the key safely</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Setting your lock options to “Never” keeps your vault available to anyone with access to your device. If you use this option, you should ensure that you keep your device properly protected.</value> <value>Setting your lock options to “Never” keeps your vault available to anyone with access to your device. If you use this option, you should ensure that you keep your device properly protected.</value>
</data> </data>
@@ -2324,7 +2312,7 @@ select Add TOTP to store the key safely</value>
<value>Allow screen capture</value> <value>Allow screen capture</value>
</data> </data>
<data name="AreYouSureYouWantToEnableScreenCapture" xml:space="preserve"> <data name="AreYouSureYouWantToEnableScreenCapture" xml:space="preserve">
<value>Are you sure you want to enable Screen Capture?</value> <value>Are you sure you want to turn on screen capture?</value>
</data> </data>
<data name="LogInRequested" xml:space="preserve"> <data name="LogInRequested" xml:space="preserve">
<value>Login requested</value> <value>Login requested</value>
@@ -2387,34 +2375,34 @@ select Add TOTP to store the key safely</value>
<value>All notifications</value> <value>All notifications</value>
</data> </data>
<data name="PasswordType" xml:space="preserve"> <data name="PasswordType" xml:space="preserve">
<value>Password Type</value> <value>Password type</value>
</data> </data>
<data name="WhatWouldYouLikeToGenerate" xml:space="preserve"> <data name="WhatWouldYouLikeToGenerate" xml:space="preserve">
<value>What would you like to generate?</value> <value>What would you like to generate?</value>
</data> </data>
<data name="UsernameType" xml:space="preserve"> <data name="UsernameType" xml:space="preserve">
<value>Username Type</value> <value>Username type</value>
</data> </data>
<data name="PlusAddressedEmail" xml:space="preserve"> <data name="PlusAddressedEmail" xml:space="preserve">
<value>Plus Addressed Email</value> <value>Plus addressed email</value>
</data> </data>
<data name="CatchAllEmail" xml:space="preserve"> <data name="CatchAllEmail" xml:space="preserve">
<value>Catch-all Email</value> <value>Catch-all email</value>
</data> </data>
<data name="ForwardedEmailAlias" xml:space="preserve"> <data name="ForwardedEmailAlias" xml:space="preserve">
<value>Forwarded Email Alias</value> <value>Forwarded email alias</value>
</data> </data>
<data name="RandomWord" xml:space="preserve"> <data name="RandomWord" xml:space="preserve">
<value>Random Word</value> <value>Random word</value>
</data> </data>
<data name="EmailRequiredParenthesis" xml:space="preserve"> <data name="EmailRequiredParenthesis" xml:space="preserve">
<value>Email (required)</value> <value>Email (required)</value>
</data> </data>
<data name="DomainNameRequiredParenthesis" xml:space="preserve"> <data name="DomainNameRequiredParenthesis" xml:space="preserve">
<value>Domain Name (required)</value> <value>Domain name (required)</value>
</data> </data>
<data name="APIKeyRequiredParenthesis" xml:space="preserve"> <data name="APIKeyRequiredParenthesis" xml:space="preserve">
<value>API Key (required)</value> <value>API key (required)</value>
</data> </data>
<data name="Service" xml:space="preserve"> <data name="Service" xml:space="preserve">
<value>Service</value> <value>Service</value>
@@ -2432,13 +2420,13 @@ select Add TOTP to store the key safely</value>
<comment>"SimpleLogin" is the product name and should not be translated.</comment> <comment>"SimpleLogin" is the product name and should not be translated.</comment>
</data> </data>
<data name="APIAccessToken" xml:space="preserve"> <data name="APIAccessToken" xml:space="preserve">
<value>API Access Token</value> <value>API access token</value>
</data> </data>
<data name="AreYouSureYouWantToOverwriteTheCurrentUsername" xml:space="preserve"> <data name="AreYouSureYouWantToOverwriteTheCurrentUsername" xml:space="preserve">
<value>Are you sure you want to overwrite the current username?</value> <value>Are you sure you want to overwrite the current username?</value>
</data> </data>
<data name="GenerateUsername" xml:space="preserve"> <data name="GenerateUsername" xml:space="preserve">
<value>Generate Username</value> <value>Generate username</value>
</data> </data>
<data name="EmailType" xml:space="preserve"> <data name="EmailType" xml:space="preserve">
<value>Email Type</value> <value>Email Type</value>
@@ -2461,6 +2449,9 @@ select Add TOTP to store the key safely</value>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Random</value> <value>Random</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Connect to Watch</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Accessibility Service Disclosure</value> <value>Accessibility Service Disclosure</value>
</data> </data>
@@ -2481,4 +2472,46 @@ select Add TOTP to store the key safely</value>
{0} {0}
Do you want to switch to this account?</value> Do you want to switch to this account?</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>New around here?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Get master password hint</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Logging in as {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log in with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Enable camera permission to use the scanner</value>
</data>
</root> </root>

View File

@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} has been copied.</value> <value>{0} has been copied.</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Verify fingerprint</value> <value>Verify fingerprint</value>
@@ -808,7 +808,7 @@
<value>You are searching for an auto-fill item for "{0}".</value> <value>You are searching for an auto-fill item for "{0}".</value>
</data> </data>
<data name="LearnOrg" xml:space="preserve"> <data name="LearnOrg" xml:space="preserve">
<value>Learn about organizations</value> <value>Learn about organisations</value>
</data> </data>
<data name="CannotOpenApp" xml:space="preserve"> <data name="CannotOpenApp" xml:space="preserve">
<value>Cannot open the app "{0}".</value> <value>Cannot open the app "{0}".</value>
@@ -1428,13 +1428,13 @@ Scanning will happen automatically.</value>
<value>Share item</value> <value>Share item</value>
</data> </data>
<data name="MoveToOrganization" xml:space="preserve"> <data name="MoveToOrganization" xml:space="preserve">
<value>Move to Organization</value> <value>Move to Organisation</value>
</data> </data>
<data name="NoOrgsToList" xml:space="preserve"> <data name="NoOrgsToList" xml:space="preserve">
<value>No organisations to list.</value> <value>No organisations to list.</value>
</data> </data>
<data name="MoveToOrgDesc" xml:space="preserve"> <data name="MoveToOrgDesc" xml:space="preserve">
<value>Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved.</value> <value>Choose an organisation that you wish to move this item to. Moving to an organisation transfers ownership of the item to that organisation. You will no longer be the direct owner of this item once it has been moved.</value>
</data> </data>
<data name="NumberOfWords" xml:space="preserve"> <data name="NumberOfWords" xml:space="preserve">
<value>Number of words</value> <value>Number of words</value>
@@ -1465,7 +1465,7 @@ Scanning will happen automatically.</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 allows you to share your vault items with others by using an organization account. Would you like to visit the bitwarden.com website to learn more?</value> <value>Bitwarden allows you to share your vault items with others by using an organisation account. Would you like to visit the bitwarden.com website to learn more?</value>
</data> </data>
<data name="ExportVault" xml:space="preserve"> <data name="ExportVault" xml:space="preserve">
<value>Export vault</value> <value>Export vault</value>
@@ -2313,9 +2313,6 @@ Scanning will happen automatically.</value>
<value>Once the key is successfully entered, <value>Once the key is successfully entered,
select Add TOTP to store the key safely</value> select Add TOTP to store the key safely</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Setting your lock options to “Never” keeps your vault available to anyone with access to your device. If you use this option, you should ensure that you keep your device properly protected.</value> <value>Setting your lock options to “Never” keeps your vault available to anyone with access to your device. If you use this option, you should ensure that you keep your device properly protected.</value>
</data> </data>
@@ -2466,6 +2463,9 @@ select Add TOTP to store the key safely</value>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Random</value> <value>Random</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Connect to Watch</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Accessibility Service Disclosure</value> <value>Accessibility Service Disclosure</value>
</data> </data>
@@ -2486,4 +2486,46 @@ select Add TOTP to store the key safely</value>
{0} {0}
Do you want to switch to this account?</value> Do you want to switch to this account?</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>New around here?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Get master password hint</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Logging in as {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Not you?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Log in with master password</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Log In with another device</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Log in initiated</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>A notification has been sent to your device.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Please make sure your vault is unlocked and the Fingerprint phrase matches on the other device.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Enable camera permission to use the scanner</value>
</data>
</root> </root>

View File

@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} ha sido copiado.</value> <value>{0} ha sido copiado.</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Verificar huella dactilar</value> <value>Verificar huella dactilar</value>
@@ -778,7 +778,7 @@
<value>Apagado</value> <value>Apagado</value>
</data> </data>
<data name="On" xml:space="preserve"> <data name="On" xml:space="preserve">
<value>Encendido</value> <value>Activado</value>
</data> </data>
<data name="Status" xml:space="preserve"> <data name="Status" xml:space="preserve">
<value>Estado</value> <value>Estado</value>
@@ -1486,7 +1486,7 @@ El escaneo se realizará automáticamente.</value>
<value>30 minutos</value> <value>30 minutos</value>
</data> </data>
<data name="SetPINDescription" xml:space="preserve"> <data name="SetPINDescription" xml:space="preserve">
<value>Establece su código PIN para desbloquear Bitwarden. Sus ajustes de PIN se reiniciarán si alguna vez cierra su sesión completamente de la aplicación.</value> <value>Establezca su código PIN para desbloquear Bitwarden. Sus ajustes de PIN se reiniciarán si alguna vez cierra su sesión completamente de la aplicación.</value>
</data> </data>
<data name="LoggedInAsOn" xml:space="preserve"> <data name="LoggedInAsOn" xml:space="preserve">
<value>Iniciado como {0} en {1}.</value> <value>Iniciado como {0} en {1}.</value>
@@ -1553,7 +1553,7 @@ El escaneo se realizará automáticamente.</value>
<value>Tema oscuro por defecto</value> <value>Tema oscuro por defecto</value>
</data> </data>
<data name="DefaultDarkThemeDescription" xml:space="preserve"> <data name="DefaultDarkThemeDescription" xml:space="preserve">
<value>Elija el tema oscuro para usar al estar usandose el tema por defecto (Sistema) mientras el modo oscuro de su dispositivo está activado.</value> <value>Elija el tema oscuro para usar al estar usándose el tema por defecto (Sistema) mientras el modo oscuro de su dispositivo está activado.</value>
</data> </data>
<data name="CopyNotes" xml:space="preserve"> <data name="CopyNotes" xml:space="preserve">
<value>Copiar notas</value> <value>Copiar notas</value>
@@ -1783,7 +1783,7 @@ El escaneo se realizará automáticamente.</value>
<value>Una o más políticas de la organización requieren que su contraseña maestra cumpla con los siguientes requisitos:</value> <value>Una o más políticas de la organización requieren que su contraseña maestra cumpla con los siguientes requisitos:</value>
</data> </data>
<data name="PolicyInEffectMinComplexity" xml:space="preserve"> <data name="PolicyInEffectMinComplexity" xml:space="preserve">
<value>Puntuación mínima de complejidad de $SCORE$</value> <value>Minimum complexity score of {0}</value>
</data> </data>
<data name="PolicyInEffectMinLength" xml:space="preserve"> <data name="PolicyInEffectMinLength" xml:space="preserve">
<value>Longitud mínima de {0}</value> <value>Longitud mínima de {0}</value>
@@ -1798,7 +1798,7 @@ El escaneo se realizará automáticamente.</value>
<value>Contiene uno o más números</value> <value>Contiene uno o más números</value>
</data> </data>
<data name="PolicyInEffectSpecial" xml:space="preserve"> <data name="PolicyInEffectSpecial" xml:space="preserve">
<value>Contiene uno o más de los siguientes caracteres especiales $CHARS$</value> <value>Contain one or more of the following special characters: {0}</value>
</data> </data>
<data name="MasterPasswordPolicyValidationTitle" xml:space="preserve"> <data name="MasterPasswordPolicyValidationTitle" xml:space="preserve">
<value>Contraseña no válida</value> <value>Contraseña no válida</value>
@@ -2300,9 +2300,6 @@ El escaneo se realizará automáticamente.</value>
<value>Una vez que la clave haya sido ingresada con éxito, <value>Una vez que la clave haya sido ingresada con éxito,
seleccione Agregar TOTP para almacenar la clave de forma segura</value> seleccione Agregar TOTP para almacenar la clave de forma segura</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Configurar las opciones de bloqueo a "Nunca" mantiene la bóveda disponible para cualquier persona con acceso a su dispositivo. Si utiliza esta opción, debe asegurarse de que mantiene su dispositivo debidamente protegido.</value> <value>Configurar las opciones de bloqueo a "Nunca" mantiene la bóveda disponible para cualquier persona con acceso a su dispositivo. Si utiliza esta opción, debe asegurarse de que mantiene su dispositivo debidamente protegido.</value>
</data> </data>
@@ -2361,7 +2358,7 @@ seleccione Agregar TOTP para almacenar la clave de forma segura</value>
<value>Aprobar solicitudes de inicio de sesión</value> <value>Aprobar solicitudes de inicio de sesión</value>
</data> </data>
<data name="UseThisDeviceToApproveLoginRequestsMadeFromOtherDevices" xml:space="preserve"> <data name="UseThisDeviceToApproveLoginRequestsMadeFromOtherDevices" xml:space="preserve">
<value>Use este dispositivo para aprovar solicitudes de incio de sesión realizadas desde otros dispositivos.</value> <value>Use este dispositivo para aprobar solicitudes de inicio de sesión realizadas desde otros dispositivos.</value>
</data> </data>
<data name="AllowNotifications" xml:space="preserve"> <data name="AllowNotifications" xml:space="preserve">
<value>Permitir notificaciones</value> <value>Permitir notificaciones</value>
@@ -2453,6 +2450,9 @@ seleccione Agregar TOTP para almacenar la clave de forma segura</value>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Aleatorio</value> <value>Aleatorio</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Conectar al reloj</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Revelación del servicio de accesibilidad</value> <value>Revelación del servicio de accesibilidad</value>
</data> </data>
@@ -2473,4 +2473,46 @@ seleccione Agregar TOTP para almacenar la clave de forma segura</value>
{0} {0}
¿Desea cambiar a esta cuenta?</value> ¿Desea cambiar a esta cuenta?</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>¿Nuevo por aquí?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Obtener pista de contraseña maestra</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Iniciando sesión como {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>¿No eres tú?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Iniciar sesión con contraseña maestra</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Iniciar sesión con otro dispositivo</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Inicio de sesión en proceso</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Se ha enviado una notificación a tu dispositivo.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Por favor, asegúrese de que su bóveda está desbloqueada y la frase de huella dactilar coincide en el otro dispositivo.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Enviar nueva notificación</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>¿Necesitas otra opción?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Ver todas las opciones de inicio de sesión</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Esta solicitud ya no es válida</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Habilitar el permiso de la cámara para usar el escáner</value>
</data>
</root> </root>

View File

@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} on kopeeritud.</value> <value>{0} on kopeeritud.</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Kinnita sõrmejäljega</value> <value>Kinnita sõrmejäljega</value>
@@ -2299,9 +2299,6 @@ Skaneerimine toimub automaatselt.</value>
<value>Pärast võtme edukat sisestamist vajuta <value>Pärast võtme edukat sisestamist vajuta
"Lisa TOTP", et see võti turvaliselt talletada</value> "Lisa TOTP", et see võti turvaliselt talletada</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Kõik, kes pääsevad sinu telefoni, saavad valikuga "Mitte kunagi" ka sinu hoidlat vaadata. Veendu, et seda tõesti teha soovid.</value> <value>Kõik, kes pääsevad sinu telefoni, saavad valikuga "Mitte kunagi" ka sinu hoidlat vaadata. Veendu, et seda tõesti teha soovid.</value>
</data> </data>
@@ -2452,6 +2449,9 @@ Skaneerimine toimub automaatselt.</value>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Juhuslik</value> <value>Juhuslik</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Ühenda kellaga</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Accessibility Service Disclosure</value> <value>Accessibility Service Disclosure</value>
</data> </data>
@@ -2472,4 +2472,46 @@ Skaneerimine toimub automaatselt.</value>
{0} {0}
Soovid selle konto peale lülituda?</value> Soovid selle konto peale lülituda?</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>Oled siin uus?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Tuleta ülemparooli vihjega meelde</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Sisselogimas kui {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Pole sina?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Logi sisse ülemparooliga</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Logi sisse läbi teise seadme</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Sisselogimine on käivitatud</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Sinu seadmesse saadeti teavitus.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Veendu, et hoidla on lahti lukustatud ja sõrmejälje fraasid seadmete vahel ühtivad.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Saada märguanne uuesti</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Soovid teist valikut kasutada?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Vaata kõiki valikuid</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>See päring ei ole enam kehtiv</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Kaamera kasutamiseks luba ligipääs kaamerale</value>
</data>
</root> </root>

View File

@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} kopiatu da.</value> <value>{0} kopiatu da.</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Egiaztatu hatz-marka</value> <value>Egiaztatu hatz-marka</value>
@@ -1575,7 +1575,7 @@
<comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment> <comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment>
</data> </data>
<data name="SolarizedDark" xml:space="preserve"> <data name="SolarizedDark" xml:space="preserve">
<value>Solarized Dark</value> <value>Solarized iluna</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">
@@ -2298,9 +2298,6 @@
<data name="OnceTheKeyIsSuccessfullyEntered" xml:space="preserve"> <data name="OnceTheKeyIsSuccessfullyEntered" xml:space="preserve">
<value>Gakoa ondo sartzen duzunean, sakatu Gehitu TOTP-a gakoa modu seguruan gordetzeko</value> <value>Gakoa ondo sartzen duzunean, sakatu Gehitu TOTP-a gakoa modu seguruan gordetzeko</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Zure blokeo aukerak "inoiz ez" bezala ezartzen badituzu, gailura sarbidea duen edonork izango du kutxa gotorra eskuragarri. Aukera hau erabiltzen baduzu, gailua behar bezala babestuta duzula ziurtatu behar duzu.</value> <value>Zure blokeo aukerak "inoiz ez" bezala ezartzen badituzu, gailura sarbidea duen edonork izango du kutxa gotorra eskuragarri. Aukera hau erabiltzen baduzu, gailua behar bezala babestuta duzula ziurtatu behar duzu.</value>
</data> </data>
@@ -2451,6 +2448,9 @@
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Ausazkoa</value> <value>Ausazkoa</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Connect to Watch</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Zabaldu irisgarritasun zerbitzua</value> <value>Zabaldu irisgarritasun zerbitzua</value>
</data> </data>
@@ -2464,11 +2464,53 @@
<value>Baztertu</value> <value>Baztertu</value>
</data> </data>
<data name="LoginRequestHasAlreadyExpired" xml:space="preserve"> <data name="LoginRequestHasAlreadyExpired" xml:space="preserve">
<value>Login request has already expired.</value> <value>Sarbide eskaera iraungi da.</value>
</data> </data>
<data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve"> <data name="LoginAttemptFromXDoYouWantToSwitchToThisAccount" xml:space="preserve">
<value>Login attempt from: <value>Saio hasiera saiakera hemendik:
{0} {0}
Do you want to switch to this account?</value> Kontu honetara aldatu nahi duzu?</value>
</data>
<data name="NewAroundHere" xml:space="preserve">
<value>Berria hemendik?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Jaso pasahitz nagusiaren pista</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>{0} bezala hasi saioa</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Ez zara zu?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Hasi saioa pasahitz nagusiarekin</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Hasi saioa beste gailu batekin</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Saioa hastea martxan da</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Jakinarazpen bat bidali da zure gailura.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Mesedez, ziurtatu kutxa gotorra desblokeatuta dagoela eta hatz-marka digitalaren esaldia bat datorrela beste gailuarekin.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Berbidali jakinarazpena</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Beste aukerarik behar al duzu?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Ikusi erregistro guztiak ezarpenetan</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Eskaera jada ez da balekoa.</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Gaitu kameraren baimena eskanerra erabiltzeko</value>
</data> </data>
</root> </root>

File diff suppressed because it is too large Load Diff

View File

@@ -376,7 +376,7 @@
</data> </data>
<data name="ValueHasBeenCopied" xml:space="preserve"> <data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} kopioitiin</value> <value>{0} kopioitiin</value>
<comment>Confirmation message after suceessfully copying a value to the clipboard.</comment> <comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data> </data>
<data name="VerifyFingerprint" xml:space="preserve"> <data name="VerifyFingerprint" xml:space="preserve">
<value>Vahvista sormenjälki</value> <value>Vahvista sormenjälki</value>
@@ -790,7 +790,7 @@
<value>Automaattinen täyttö</value> <value>Automaattinen täyttö</value>
</data> </data>
<data name="AutofillOrView" xml:space="preserve"> <data name="AutofillOrView" xml:space="preserve">
<value>Haluatko täyttää kohteella automaatisesti vai tarkastella sen tietoja?</value> <value>Täytetäänkö automaatisesti vai näytetäänkö tiedot?</value>
</data> </data>
<data name="BitwardenAutofillServiceMatchConfirm" xml:space="preserve"> <data name="BitwardenAutofillServiceMatchConfirm" xml:space="preserve">
<value>Haluatko varmasti täyttää automaattisesti tällä kohteella? Se ei täsmää täysin osoitteen "{0}" kanssa.</value> <value>Haluatko varmasti täyttää automaattisesti tällä kohteella? Se ei täsmää täysin osoitteen "{0}" kanssa.</value>
@@ -1762,7 +1762,7 @@ Koodi luetaan automaattisesti.</value>
<value>Synkronoidaan holvi alasveto-eleellä.</value> <value>Synkronoidaan holvi alasveto-eleellä.</value>
</data> </data>
<data name="LogInSso" xml:space="preserve"> <data name="LogInSso" xml:space="preserve">
<value>Kertakirjautuminen (SSO)</value> <value>Yrityksen kertakirjautuminen (SSO)</value>
</data> </data>
<data name="LogInSsoSummary" xml:space="preserve"> <data name="LogInSsoSummary" xml:space="preserve">
<value>Kirjaudu sisään käyttäen organisaatiosi kertakirjautumista (SSO). Syötä organisaatiosi tunniste aloittaaksesi.</value> <value>Kirjaudu sisään käyttäen organisaatiosi kertakirjautumista (SSO). Syötä organisaatiosi tunniste aloittaaksesi.</value>
@@ -1810,7 +1810,8 @@ Koodi luetaan automaattisesti.</value>
<value>Ladataan</value> <value>Ladataan</value>
</data> </data>
<data name="AcceptPolicies" xml:space="preserve"> <data name="AcceptPolicies" xml:space="preserve">
<value>Aktivoimalla tämän valinnan hyväksyt seuraavat: </value> <value>Valitsemalla tämän hyväksyt seuraavat:
</value>
</data> </data>
<data name="AcceptPoliciesError" xml:space="preserve"> <data name="AcceptPoliciesError" xml:space="preserve">
<value>Palveluehtoja ja tietosuojakäytäntöä ei ole vahvistettu.</value> <value>Palveluehtoja ja tietosuojakäytäntöä ei ole vahvistettu.</value>
@@ -2299,9 +2300,6 @@ Koodi luetaan automaattisesti.</value>
<value>Kun koodi on syötetty oikein, tallenna avain <value>Kun koodi on syötetty oikein, tallenna avain
turvallisesti valitsemalla "Lisää TOTP"</value> turvallisesti valitsemalla "Lisää TOTP"</value>
</data> </data>
<data name="SelectAddTotpToStoreTheKeySafely" xml:space="preserve">
<value></value>
</data>
<data name="NeverLockWarning" xml:space="preserve"> <data name="NeverLockWarning" xml:space="preserve">
<value>Käyttämällä lukitusasetusta "Ei koskaan"? Tallentuu holvisi salausavain laitteellesi. Jos käytät asetusta, varmista, että laite on suojattu hyvin.</value> <value>Käyttämällä lukitusasetusta "Ei koskaan"? Tallentuu holvisi salausavain laitteellesi. Jos käytät asetusta, varmista, että laite on suojattu hyvin.</value>
</data> </data>
@@ -2324,7 +2322,7 @@ turvallisesti valitsemalla "Lisää TOTP"</value>
<value>Yritätkö kirjautua sisään?</value> <value>Yritätkö kirjautua sisään?</value>
</data> </data>
<data name="LogInAttemptByXOnY" xml:space="preserve"> <data name="LogInAttemptByXOnY" xml:space="preserve">
<value>{0} yrittää kirjautua laitteella {1}</value> <value>Kirjautumisyritys tunnuksella {0} laitteella {1}</value>
</data> </data>
<data name="DeviceType" xml:space="preserve"> <data name="DeviceType" xml:space="preserve">
<value>Laitteen tyyppi</value> <value>Laitteen tyyppi</value>
@@ -2452,6 +2450,9 @@ turvallisesti valitsemalla "Lisää TOTP"</value>
<data name="Random" xml:space="preserve"> <data name="Random" xml:space="preserve">
<value>Satunnainen</value> <value>Satunnainen</value>
</data> </data>
<data name="ConnectToWatch" xml:space="preserve">
<value>Yhdistä Watchiin</value>
</data>
<data name="AccessibilityServiceDisclosure" xml:space="preserve"> <data name="AccessibilityServiceDisclosure" xml:space="preserve">
<value>Esteettömyyspalvelun kuvaus</value> <value>Esteettömyyspalvelun kuvaus</value>
</data> </data>
@@ -2472,4 +2473,46 @@ turvallisesti valitsemalla "Lisää TOTP"</value>
{0} {0}
Haluatko vaihtaa tähän tiliin?</value> Haluatko vaihtaa tähän tiliin?</value>
</data> </data>
<data name="NewAroundHere" xml:space="preserve">
<value>Oletko uusi täällä?</value>
</data>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Pyydä pääsalasanan vihjettä</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Kirjaudutaan tunnuksella {0}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Etkö se ollut sinä?</value>
</data>
<data name="LogInWithMasterPassword" xml:space="preserve">
<value>Kirjaudu pääsalasanalla</value>
</data>
<data name="LogInWithAnotherDevice" xml:space="preserve">
<value>Kirjaudu toisella laitteella</value>
</data>
<data name="LogInInitiated" xml:space="preserve">
<value>Kirjautuminen aloitettu</value>
</data>
<data name="ANotificationHasBeenSentToYourDevice" xml:space="preserve">
<value>Laitteellesi on lähetetty ilmoitus.</value>
</data>
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
<value>Varmista, että holvisi on avattu ja tunnistelauseke täsmää toisella laitteella.</value>
</data>
<data name="ResendNotification" xml:space="preserve">
<value>Lähetä ilmoitus uudelleen</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Tarvitsetko toisen vaihtoehdon?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>Näytä kaikki kirjautumisvaihtoehdot</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>Pyyntö ei ole enää voimassa.</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Myönnä kameran käyttöoikeus skannerin käyttämiseksi</value>
</data>
</root> </root>

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