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

Compare commits

..

150 Commits

Author SHA1 Message Date
Kyle Spearrin
40d68b1654 add event service 2019-07-11 09:30:25 -04:00
Kyle Spearrin
a240a4ac66 get autofill web scheme for android p devices 2019-07-11 08:55:40 -04:00
Kyle Spearrin
416ec3812d iphone x screenshots 2019-07-10 14:17:28 -04:00
Kyle Spearrin
ff24891903 update event log types 2019-07-09 10:51:33 -04:00
Kyle Spearrin
ddcbe298ac 6.5 inch screenshots for ios 2019-07-09 09:48:27 -04:00
Kyle Spearrin
6d8f647aee two new screenshots for iphone, update 1 2019-07-09 01:09:53 -04:00
Kyle Spearrin
a654987175 upadte screenshots for 5.5 inch iphone 6 2019-07-08 17:34:04 -04:00
Kyle Spearrin
a5f960d8a1 show proper name for faceid. homepage margin on ios 2019-07-08 13:37:45 -04:00
Kyle Spearrin
1f707cda68 New Crowdin translations (#556)
* New translations AppResources.resx (Portuguese)

* New translations AppResources.resx (Russian)

* New translations AppResources.resx (Czech)

* New translations AppResources.resx (Hebrew)

* New translations AppResources.resx (French)
2019-07-08 13:12:09 -04:00
Kyle Spearrin
4e7f195fd2 bump versions 2019-07-08 13:02:48 -04:00
Kyle Spearrin
7728e930be delay focus on entry on ios too 2019-07-08 12:06:37 -04:00
Kyle Spearrin
ab84200347 change default lock on new installs to 15 minutes 2019-07-06 23:04:10 -04:00
Kyle Spearrin
62d8824450 clear cache in main app if change made in extension 2019-07-06 22:49:17 -04:00
Kyle Spearrin
cf35d20adb refresh search on appear if has text 2019-07-06 22:19:29 -04:00
Kyle Spearrin
65725b5a38 yubikey token must be > 40 in length too 2019-07-06 22:09:20 -04:00
Kyle Spearrin
eca4777b99 yubikey fixes for ios 2019-07-06 21:59:13 -04:00
Kyle Spearrin
066b3aba5b wait 5 seconds after migration 2019-07-05 17:37:21 -04:00
Kyle Spearrin
8e485ff26f add back refs for extensions 2019-07-05 17:14:08 -04:00
Kyle Spearrin
341b66f44f settings shim with ios group id 2019-07-05 17:10:37 -04:00
Kyle Spearrin
19c62d3320 Merge branch 'master' of github.com:bitwarden/mobile 2019-07-05 16:37:12 -04:00
Kyle Spearrin
13ffbd7675 add app extension flags to migration 2019-07-05 16:36:56 -04:00
Kyle Spearrin
9af6aae699 fix baseurl check when return web vault url 2019-07-05 13:46:54 -04:00
Kyle Spearrin
2e562e8318 ios migration from old version 2019-07-05 13:35:22 -04:00
Kyle Spearrin
c6db763716 New Crowdin translations (#554)
* New translations AppResources.resx (English, United Kingdom)

* New translations AppResources.resx (Persian)

* New translations AppResources.resx (Estonian)

* New translations AppResources.resx (Persian)

* New translations AppResources.resx (Spanish)

* New translations AppResources.resx (Portuguese, Brazilian)

* New translations AppResources.resx (Polish)

* New translations AppResources.resx (Catalan)

* New translations AppResources.resx (Dutch)

* New translations AppResources.resx (Danish)

* New translations AppResources.resx (Danish)

* New translations AppResources.resx (Japanese)

* New translations AppResources.resx (Chinese Traditional)

* New translations AppResources.resx (Dutch)

* New translations AppResources.resx (Spanish)

* New translations AppResources.resx (Italian)

* New translations AppResources.resx (French)

* New translations AppResources.resx (French)

* New translations AppResources.resx (Chinese Simplified)

* New translations AppResources.resx (Czech)

* New translations AppResources.resx (Ukrainian)
2019-07-04 08:43:40 -04:00
Kyle Spearrin
a3383af4ae hides shadow on nav bar 2019-07-03 20:39:00 -04:00
Kyle Spearrin
6c56e44b61 prefix keychain key with appid 2019-07-03 20:04:23 -04:00
Kyle Spearrin
64506a7080 UINavigationBar appearance for no bottom line 2019-07-03 17:37:33 -04:00
Kyle Spearrin
fac9ae4b6c only init hockeyapp once 2019-07-03 16:50:12 -04:00
Kyle Spearrin
a2dc73afef New Crowdin translations (#553)
* New translations AppResources.resx (Afrikaans)

* New translations AppResources.resx (Korean)

* New translations AppResources.resx (Persian)

* New translations AppResources.resx (Norwegian Bokmal)

* New translations AppResources.resx (Japanese)

* New translations AppResources.resx (Italian)

* New translations AppResources.resx (Indonesian)

* New translations AppResources.resx (Polish)

* New translations AppResources.resx (Hungarian)

* New translations AppResources.resx (Swedish)

* New translations AppResources.resx (Spanish)

* New translations AppResources.resx (Slovak)

* New translations AppResources.resx (Portuguese)

* New translations AppResources.resx (Russian)

* New translations AppResources.resx (Romanian)

* New translations AppResources.resx (Portuguese, Brazilian)

* New translations AppResources.resx (Chinese Traditional)

* New translations AppResources.resx (Danish)

* New translations AppResources.resx (Croatian)

* New translations AppResources.resx (Chinese Simplified)

* New translations AppResources.resx (Catalan)

* New translations AppResources.resx (Bulgarian)

* New translations AppResources.resx (Czech)

* New translations AppResources.resx (Dutch)

* New translations AppResources.resx (French)

* New translations AppResources.resx (Hindi)

* New translations AppResources.resx (Hebrew)

* New translations AppResources.resx (German)

* New translations AppResources.resx (Finnish)

* New translations AppResources.resx (Estonian)

* New translations AppResources.resx (English, United Kingdom)

* New translations AppResources.resx (Ukrainian)

* New translations AppResources.resx (Vietnamese)

* New translations AppResources.resx (Turkish)

* New translations AppResources.resx (Thai)
2019-07-03 15:15:21 -04:00
Kyle Spearrin
59c5a34cd0 adjust bundle signing config 2019-07-03 15:03:09 -04:00
Kyle Spearrin
3321e6b0e2 set entitlements 2019-07-03 14:54:12 -04:00
Kyle Spearrin
8b7ac179fa in memory storage service 2019-07-03 12:31:18 -04:00
Kyle Spearrin
ea745665c8 remove continue button if no 2fa available 2019-07-03 12:21:06 -04:00
Kyle Spearrin
ca8f6ee10b FFImageLoading only for main app 2019-07-03 10:08:59 -04:00
Kyle Spearrin
3e51ff46f3 forget bg colors :( 2019-07-02 23:31:52 -04:00
Kyle Spearrin
fa2e814559 style headers and footer 2019-07-02 22:27:21 -04:00
Kyle Spearrin
87e337cbeb try color header bg again 2019-07-02 20:52:44 -04:00
Kyle Spearrin
abb39df547 reset service container from extensions 2019-07-02 20:45:54 -04:00
Kyle Spearrin
43e15bf911 more bg color for header 2019-07-02 20:14:23 -04:00
Kyle Spearrin
4d79d0af89 bg for header/footer is tint color 2019-07-02 19:49:50 -04:00
Kyle Spearrin
69100d7db5 search bar bg is same as list header 2019-07-02 19:36:11 -04:00
Kyle Spearrin
a064a6cf9b theme updates to extensions 2019-07-02 19:35:01 -04:00
Kyle Spearrin
7953a9a3ce autofill activated regular color 2019-07-02 17:28:57 -04:00
Kyle Spearrin
be3c6f210d remove see apps from ext page 2019-07-02 17:27:55 -04:00
Kyle Spearrin
f7cbddab4b remove navibar outlet 2019-07-02 17:17:20 -04:00
Kyle Spearrin
d423818764 add hockeyapp to extensions 2019-07-02 16:28:01 -04:00
Kyle Spearrin
519acd43aa provisioning profiles 2019-07-02 16:13:09 -04:00
Kyle Spearrin
2682a0d9e4 --nodevcodeshare on debug 2019-07-02 14:58:18 -04:00
Kyle Spearrin
8629ae048c update build props 2019-07-02 14:43:07 -04:00
Kyle Spearrin
905d01e804 adjust settings 2019-07-02 14:14:59 -04:00
Kyle Spearrin
0588bbc41d remove remaining jsonnet deps 2019-07-02 14:06:21 -04:00
Kyle Spearrin
b308b4c54f move some json dependencies out of extension project 2019-07-02 14:03:59 -04:00
Kyle Spearrin
c2c73d5460 autofill pages for ios 2019-07-02 13:15:00 -04:00
Kyle Spearrin
e01bf57874 re-set state for website icons on login/unlock
resolves #549
2019-07-02 08:05:34 -04:00
Kyle Spearrin
7ced93225b logic on autoPromptFingerprint when locked 2019-07-02 07:50:09 -04:00
Kyle Spearrin
b5e61864af adjust header for autofill page 2019-07-02 00:19:59 -04:00
Kyle Spearrin
1e5aaea8f4 restore lockOptionMs 2019-07-01 23:45:31 -04:00
Kyle Spearrin
ab3bebf06a use background tasks to keep timers alive 2019-07-01 23:44:47 -04:00
Kyle Spearrin
4a294d6a77 save some lines 2019-07-01 21:16:28 -04:00
Kyle Spearrin
e0fda1a0bc fix ui thread issue 2019-07-01 21:15:53 -04:00
Kyle Spearrin
d17da80f19 lock timer 2019-07-01 21:10:24 -04:00
Kyle Spearrin
2e7658f857 clear clipboard timer 2019-07-01 16:56:42 -04:00
Kyle Spearrin
53d0b28c7c fix add matching eq domains
resolves #550
2019-07-01 16:06:52 -04:00
Kyle Spearrin
33ba4d3871 add capitalize and include num to generator 2019-07-01 15:35:26 -04:00
Kyle Spearrin
225db6397d ios app extension theming 2019-07-01 15:12:54 -04:00
Nicholas
73b5d1b3f1 add support for org.mozilla.fenix.nightly (#551)
* Update autofillservice.xml

* Update AutofillHelpers.cs

* Update AccessibilityHelpers.cs
2019-07-01 11:35:58 -04:00
Kyle Spearrin
8da2eac6d0 add support for org.mozilla.fennec_fdroid
resolves #548
2019-06-28 23:23:51 -04:00
Kyle Spearrin
fbd62153ee theme splash for extensions 2019-06-28 12:30:48 -04:00
Kyle Spearrin
9145fa1c48 improvement to lock screen 2019-06-28 11:47:04 -04:00
Kyle Spearrin
caa0af1258 remove old action view controllers 2019-06-28 10:45:42 -04:00
Kyle Spearrin
7a230ee5f5 app extension for autofill ios 2019-06-28 08:57:08 -04:00
Kyle Spearrin
f237fa98d2 ios autofill extension implemented 2019-06-28 08:21:44 -04:00
Kyle Spearrin
be4ae605a9 implement ASHelpers from messages 2019-06-27 16:22:58 -04:00
Kyle Spearrin
9c2cbc0ecb add shared controllers and view to ios core 2019-06-27 15:48:25 -04:00
Kyle Spearrin
fb3009fc66 core utils 2019-06-27 14:07:25 -04:00
Kyle Spearrin
04c32e28cd move device action to ios core 2019-06-27 13:58:08 -04:00
Kyle Spearrin
645576c949 port over models 2019-06-27 13:45:16 -04:00
Kyle Spearrin
775bee3546 fix dependency hell 2019-06-27 13:41:32 -04:00
Kyle Spearrin
88aea96034 add autofill resources 2019-06-26 20:52:17 -04:00
Kyle Spearrin
5f474dfaf5 add some missing resources 2019-06-26 20:43:14 -04:00
Kyle Spearrin
fe7aad0835 autofill extension project 2019-06-26 20:39:45 -04:00
Kyle Spearrin
79746efa2d action extension project 2019-06-26 20:28:23 -04:00
Kyle Spearrin
a158021f46 return selection collection logic 2019-06-26 17:50:57 -04:00
Kyle Spearrin
2d91a893f7 fix cursor color to renderers 2019-06-26 10:20:42 -04:00
Kyle Spearrin
dd4561d985 style cursor color 2019-06-26 10:12:34 -04:00
Kyle Spearrin
92764eeae0 hide status bar on homepage for ios 2019-06-26 10:05:31 -04:00
Kyle Spearrin
b72808ab40 splash screen bg colors and white logo 2019-06-26 09:35:18 -04:00
Kyle Spearrin
14f3f99218 fix attachments selection on ios 2019-06-25 17:46:37 -04:00
Kyle Spearrin
d7130d9b67 no entities state adjustments 2019-06-25 17:16:47 -04:00
Kyle Spearrin
3f94eee4d5 events url 2019-06-25 16:36:21 -04:00
Kyle Spearrin
72cbdcbc8d use internal FilesDir for temp photo 2019-06-25 11:54:31 -04:00
Kyle Spearrin
e33b49e78c externalsFileDir w/ FileProvider for temp store 2019-06-25 10:30:16 -04:00
Kyle Spearrin
8e04945d4e box-row-input-options-platform on share 2019-06-24 17:38:29 -04:00
Kyle Spearrin
3ca5da55cb fix more options for sharing on view/add/edit 2019-06-24 17:34:00 -04:00
Kyle Spearrin
ea30373a09 picker SetUpdateMode for ios 2019-06-24 17:32:24 -04:00
Kyle Spearrin
4b4757d0e5 ios resumed 2019-06-24 17:02:05 -04:00
Kyle Spearrin
4bc837509d fix double key formatting 2019-06-24 16:51:54 -04:00
Kyle Spearrin
c9d1e8dc65 nord theme toast for ios 2019-06-24 16:29:02 -04:00
Kyle Spearrin
88b8a192b5 no listview selection type on non-light theme 2019-06-24 16:16:17 -04:00
Kyle Spearrin
94fbf627ba no options during selection mode 2019-06-24 15:22:46 -04:00
Kyle Spearrin
45fbdb8411 ios theming 2019-06-24 15:13:33 -04:00
Kyle Spearrin
d9c947ccd0 black theme for ios 2019-06-24 14:49:47 -04:00
Kyle Spearrin
2b670a5ae1 ios themeing 2019-06-24 14:29:23 -04:00
Kyle Spearrin
1af0178b50 set theme properly on app launch for ios 2019-06-24 12:23:00 -04:00
Kyle Spearrin
3ec5d894b3 spacing for ios on options page 2019-06-24 12:05:01 -04:00
Kyle Spearrin
d81585ccc3 search bar for ios 2019-06-24 11:53:19 -04:00
Kyle Spearrin
38f91bce1c notes separator for ios 2019-06-24 11:22:34 -04:00
Kyle Spearrin
2d41dd6ae0 switch styling on iOS 2019-06-22 09:51:04 -04:00
Kyle Spearrin
1705a21f68 slider styling 2019-06-22 09:45:54 -04:00
Kyle Spearrin
164d79898a button styling 2019-06-22 09:15:37 -04:00
Kyle Spearrin
50f809d290 undo busy when syncing complete 2019-06-21 16:53:17 -04:00
Kyle Spearrin
39284b475d bottom border on picker and no padding on editor 2019-06-21 16:36:23 -04:00
Kyle Spearrin
d44950d46c bottom border for ios entry 2019-06-21 16:09:20 -04:00
Kyle Spearrin
e9b55bc207 fix tag issue on settings page 2019-06-21 10:01:35 -04:00
Kyle Spearrin
5470f08fee list-row-header-container bg color 2019-06-21 09:59:22 -04:00
Kyle Spearrin
f9a3bbd7fa remove green background 2019-06-21 09:47:10 -04:00
Kyle Spearrin
9d3165dc65 New grid layout structure for cipher view cell 2019-06-21 09:46:46 -04:00
Kyle Spearrin
3475d39f37 use bold colored headers 2019-06-20 17:26:42 -04:00
Kyle Spearrin
44782b1ddf header upper on iOS 2019-06-20 17:05:28 -04:00
Kyle Spearrin
dd8d5fd84c icon sizes for ios 2019-06-20 16:49:27 -04:00
Kyle Spearrin
e8f2d9d0dd list section border colors 2019-06-20 16:40:13 -04:00
Kyle Spearrin
a2de3b5d80 remove binding context from header viewcell 2019-06-20 16:34:17 -04:00
Kyle Spearrin
a2960c45bc accessible font sizes 2019-06-20 16:32:22 -04:00
Kyle Spearrin
dc91624597 some listview styling for iOS 2019-06-20 16:02:39 -04:00
Kyle Spearrin
223ec180fc disable spell check & prediction on certain fields 2019-06-19 16:03:55 -04:00
Kyle Spearrin
0116572fec show nested collections in groupings pages 2019-06-17 10:21:05 -04:00
Kyle Spearrin
5350e5385c version bump 2019-06-16 06:57:25 -04:00
Kyle Spearrin
8f18c4fd45 cleartextTrafficPermitted 2019-06-16 06:54:58 -04:00
Kyle Spearrin
8538fbabe5 dont link core lib 2019-06-15 22:50:54 -04:00
Kyle Spearrin
9367b34bbe more linking 2019-06-15 21:58:43 -04:00
Kyle Spearrin
a766044cb4 bump version 2019-06-15 21:13:12 -04:00
Kyle Spearrin
0eb385e49f revert com.android.settings from blacklist 2019-06-15 21:02:38 -04:00
Kyle Spearrin
e30136dace just check if !HasCiphers 2019-06-15 20:44:36 -04:00
Kyle Spearrin
c50dee479a android http client handler 2019-06-15 18:44:08 -04:00
Kyle Spearrin
58ef292fa7 null checks 2019-06-15 00:14:32 -04:00
Kyle Spearrin
61b728fea7 x86 builds as well 2019-06-14 23:32:58 -04:00
Kyle Spearrin
b782eeb839 fixes to 2fa page 2019-06-14 18:08:08 -04:00
Kyle Spearrin
77314d4b8d cleanup search page for ios 2019-06-14 17:40:21 -04:00
Kyle Spearrin
c79d1d24b3 add and more toolbar buttons for ios 2019-06-14 17:31:06 -04:00
Kyle Spearrin
5dbea8ca09 more options on generator and history page 2019-06-14 17:21:17 -04:00
Kyle Spearrin
09a1c17fb4 null checks 2019-06-14 16:53:01 -04:00
Kyle Spearrin
a0632bcac2 null checks 2019-06-14 16:22:56 -04:00
Kyle Spearrin
07d57ebe8c bump version 2019-06-14 08:46:04 -04:00
Kyle Spearrin
325c88018c more menu for ios 2019-06-14 08:45:28 -04:00
Kyle Spearrin
dcb1102746 crash fixes 2019-06-14 08:05:28 -04:00
Kyle Spearrin
636d3c02c4 catch errors 2019-06-13 20:41:24 -04:00
Kyle Spearrin
5b119ded17 x64 builds as well 2019-06-13 16:25:13 -04:00
Kyle Spearrin
f25ae870c5 hebrew fix 2019-06-13 16:07:08 -04:00
Kyle Spearrin
49673262e4 bump version and fix readme 2019-06-13 15:05:31 -04:00
vargbeaumont
3ed814c1f7 Update styles.xml (#537)
Fix black navigation bar on none Google ROMs.
2019-06-13 15:03:00 -04:00
289 changed files with 10482 additions and 1209 deletions

View File

@@ -8,7 +8,7 @@
The Bitwarden mobile application is written in C# with Xamarin Android, Xamarin iOS, and Xamarin Forms.
<img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-android.png" alt="" width="300" height="533" /> <img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-ios.png" alt="" width="300" height="533" />
<img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-android-myvault.png" alt="" width="300" height="533" /> <img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-ios-myvault.png" alt="" width="300" height="533" />
# Build/Run

View File

@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.539
# Visual Studio Version 16
VisualStudioVersion = 16.0.29009.5
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Android", "src\Android\Android.csproj", "{304400AF-F0ED-40FA-B102-EA3C3EC43E4F}"
EndProject
@@ -35,6 +35,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Core", "src\iOS.Core\iO
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS", "src\iOS\iOS.csproj", "{599E0201-420A-4C3E-A7BA-5349F72E0B15}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Extension", "src\iOS.Extension\iOS.Extension.csproj", "{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Autofill", "src\iOS.Autofill\iOS.Autofill.csproj", "{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@@ -99,24 +103,24 @@ Global
{304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{304400AF-F0ED-40FA-B102-EA3C3EC43E4F}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|Any CPU.Deploy.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhone.Deploy.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|Any CPU.Deploy.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhone.Build.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhone.Deploy.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhoneSimulator.Deploy.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|Any CPU.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhone.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|Any CPU.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|Any CPU.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhone.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhone.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.AppStore|iPhoneSimulator.Deploy.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
@@ -141,18 +145,18 @@ Global
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|iPhone.Build.0 = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|Any CPU.Build.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|iPhone.Build.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B8A8C41-9820-4341-974C-41E65B7F4366}.Debug|iPhone.ActiveCfg = Debug|Any CPU
@@ -231,18 +235,18 @@ Global
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|iPhone.Build.0 = Release|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|Any CPU.ActiveCfg = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|Any CPU.Build.0 = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.ActiveCfg = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.Build.0 = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhoneSimulator.ActiveCfg = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhoneSimulator.Build.0 = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|Any CPU.ActiveCfg = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|Any CPU.Build.0 = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhone.ActiveCfg = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhone.Build.0 = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhoneSimulator.ActiveCfg = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhoneSimulator.Build.0 = FDroid|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|Any CPU.Build.0 = Ad-Hoc|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|Any CPU.ActiveCfg = AppStore|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|Any CPU.Build.0 = AppStore|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhone.ActiveCfg = AppStore|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhone.Build.0 = AppStore|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.AppStore|iPhoneSimulator.Build.0 = AppStore|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E71F3053-056C-4381-9638-048ED73BDFF6}.Debug|iPhone.ActiveCfg = Debug|Any CPU
@@ -286,6 +290,62 @@ Global
{599E0201-420A-4C3E-A7BA-5349F72E0B15}.Release|iPhone.Build.0 = Release|iPhone
{599E0201-420A-4C3E-A7BA-5349F72E0B15}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{599E0201-420A-4C3E-A7BA-5349F72E0B15}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|Any CPU.Build.0 = Ad-Hoc|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|Any CPU.Build.0 = AppStore|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|iPhone.Build.0 = AppStore|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|Any CPU.ActiveCfg = Debug|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|iPhone.ActiveCfg = Debug|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|iPhone.Build.0 = Debug|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|Any CPU.ActiveCfg = Release|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|Any CPU.Build.0 = Release|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|iPhone.ActiveCfg = Release|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|iPhone.Build.0 = Release|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.FDroid|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|Any CPU.ActiveCfg = Release|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhone.ActiveCfg = Release|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhone.Build.0 = Release|iPhone
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|Any CPU.Build.0 = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|Any CPU.Build.0 = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhone.Build.0 = AppStore|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|Any CPU.ActiveCfg = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhone.ActiveCfg = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhone.Build.0 = Debug|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|Any CPU.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|Any CPU.Build.0 = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhone.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhone.Build.0 = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.FDroid|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|Any CPU.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhone.ActiveCfg = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhone.Build.0 = Release|iPhone
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -299,6 +359,8 @@ Global
{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D} = {2E399654-26A2-46F6-B9CA-1B496A3F370A}
{E71F3053-056C-4381-9638-048ED73BDFF6} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{599E0201-420A-4C3E-A7BA-5349F72E0B15} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{324BE76C-38FA-4F11-8BB1-95C7B3B1B545} = {D10CA4A9-F866-40E1-B658-F69051236C71}
{8A3ECD75-3EC8-4CB3-B3A2-A73A724C279A} = {D10CA4A9-F866-40E1-B658-F69051236C71}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7D436EA3-8B7E-45D2-8D14-0730BD2E0410}

View File

@@ -37,9 +37,11 @@ namespace Bit.Droid.Accessibility
new Browser("org.mozilla.firefox", "url_bar_title"),
new Browser("org.mozilla.firefox_beta", "url_bar_title"),
new Browser("org.mozilla.fennec_aurora", "url_bar_title"),
new Browser("org.mozilla.fennec_fdroid", "url_bar_title"),
new Browser("org.mozilla.focus", "display_url"),
new Browser("org.mozilla.klar", "display_url"),
new Browser("org.mozilla.fenix", "mozac_browser_toolbar_url_view"),
new Browser("org.mozilla.fenix.nightly", "mozac_browser_toolbar_url_view"),
new Browser("org.mozilla.reference.browser", "mozac_browser_toolbar_url_view"),
new Browser("com.ghostery.android.ghostery", "search_field"),
new Browser("org.adblockplus.browser", "url_bar_title"),
@@ -243,4 +245,4 @@ namespace Bit.Droid.Accessibility
return allEditTexts.TakeWhile(n => !n.Password).LastOrDefault();
}
}
}
}

View File

@@ -33,10 +33,10 @@
<AndroidEnableMultiDex>true</AndroidEnableMultiDex>
<AndroidSupportedAbis />
<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
<AndroidLinkSkip>Xamarin.GooglePlayServices.Base;Xamarin.GooglePlayServices.Basement;Xamarin.GooglePlayServices.Measurement;Xamarin.GooglePlayServices.Gcm;BitwardenAndroid;BitwardenApp;Xamarin.Android.Net</AndroidLinkSkip>
<AndroidLinkSkip>Xamarin.GooglePlayServices.Base;Xamarin.GooglePlayServices.Basement;Xamarin.GooglePlayServices.Measurement;Xamarin.GooglePlayServices.Gcm;BitwardenAndroid;BitwardenApp;BitwardenCore;Xamarin.Android.Net</AndroidLinkSkip>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugSymbols>false</DebugSymbols>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
@@ -44,13 +44,15 @@
<WarningLevel>4</WarningLevel>
<AndroidManagedSymbols>true</AndroidManagedSymbols>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
<AndroidSupportedAbis />
<AndroidSupportedAbis>armeabi-v7a;x86;x86_64;arm64-v8a</AndroidSupportedAbis>
<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
<AndroidEnableMultiDex>true</AndroidEnableMultiDex>
<AndroidLinkSkip>Xamarin.GooglePlayServices.Base;Xamarin.GooglePlayServices.Basement;Xamarin.GooglePlayServices.Measurement;Xamarin.GooglePlayServices.Gcm;BitwardenAndroid;BitwardenApp;Xamarin.Android.Net</AndroidLinkSkip>
<AndroidLinkSkip>Xamarin.GooglePlayServices.Base;Xamarin.GooglePlayServices.Basement;Xamarin.GooglePlayServices.Measurement;Xamarin.GooglePlayServices.Gcm;BitwardenAndroid;BitwardenApp;BitwardenCore;Xamarin.Android.Net</AndroidLinkSkip>
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
<AndroidLinkMode>Full</AndroidLinkMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'FDroid|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<DebugSymbols>false</DebugSymbols>
<OutputPath>bin\FDroid\</OutputPath>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
@@ -59,12 +61,13 @@
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<DefineConstants>FDROID</DefineConstants>
<AndroidSupportedAbis />
<AndroidSupportedAbis>armeabi-v7a;x86;x86_64;arm64-v8a</AndroidSupportedAbis>
<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
<AndroidEnableMultiDex>true</AndroidEnableMultiDex>
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
<AndroidLinkSkip>Xamarin.GooglePlayServices.Base;Xamarin.GooglePlayServices.Basement;Xamarin.GooglePlayServices.Measurement;Xamarin.GooglePlayServices.Gcm;BitwardenAndroid;BitwardenApp;Xamarin.Android.Net</AndroidLinkSkip>
<AndroidLinkSkip>Xamarin.GooglePlayServices.Base;Xamarin.GooglePlayServices.Basement;Xamarin.GooglePlayServices.Measurement;Xamarin.GooglePlayServices.Gcm;BitwardenAndroid;BitwardenApp;BitwardenCore;Xamarin.Android.Net</AndroidLinkSkip>
<AndroidLinkMode>Full</AndroidLinkMode>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Android" />

View File

@@ -53,9 +53,11 @@ namespace Bit.Droid.Autofill
"com.ecosia.android",
"com.opera.mini.native.beta",
"org.mozilla.fennec_aurora",
"org.mozilla.fennec_fdroid",
"com.qwant.liberty",
"com.opera.touch",
"org.mozilla.fenix",
"org.mozilla.fenix.nightly",
"org.mozilla.reference.browser",
"org.mozilla.rocket",
};
@@ -66,7 +68,6 @@ namespace Bit.Droid.Autofill
"androidapp://android",
"androidapp://com.x8bit.bitwarden",
"androidapp://com.oneplus.applocker",
"androidapp://com.android.settings",
};
public static async Task<List<FilledItem>> GetFillItemsAsync(Parser parser, ICipherService cipherService)

View File

@@ -5,6 +5,7 @@ using Bit.Core;
using Android.Content;
using Bit.Core.Abstractions;
using System.Threading.Tasks;
using Android.OS;
namespace Bit.Droid.Autofill
{
@@ -17,7 +18,7 @@ namespace Bit.Droid.Autofill
private readonly AssistStructure _structure;
private string _uri;
private string _packageName;
private string _webDomain;
private string _website;
public Parser(AssistStructure structure, Context applicationContext)
{
@@ -36,14 +37,14 @@ namespace Bit.Droid.Autofill
{
return _uri;
}
var webDomainNull = string.IsNullOrWhiteSpace(WebDomain);
if(webDomainNull && string.IsNullOrWhiteSpace(PackageName))
var websiteNull = string.IsNullOrWhiteSpace(Website);
if(websiteNull && string.IsNullOrWhiteSpace(PackageName))
{
_uri = null;
}
else if(!webDomainNull)
else if(!websiteNull)
{
_uri = string.Concat("http://", WebDomain);
_uri = Website;
}
else
{
@@ -66,16 +67,16 @@ namespace Bit.Droid.Autofill
}
}
public string WebDomain
public string Website
{
get => _webDomain;
get => _website;
set
{
if(string.IsNullOrWhiteSpace(value))
{
_webDomain = _uri = null;
_website = _uri = null;
}
_webDomain = value;
_website = value;
}
}
@@ -104,7 +105,7 @@ namespace Bit.Droid.Autofill
if(!AutofillHelpers.TrustedBrowsers.Contains(PackageName) &&
!AutofillHelpers.CompatBrowsers.Contains(PackageName))
{
WebDomain = null;
Website = null;
}
}
@@ -135,9 +136,14 @@ namespace Bit.Droid.Autofill
{
PackageName = node.IdPackage;
}
if(string.IsNullOrWhiteSpace(WebDomain) && !string.IsNullOrWhiteSpace(node.WebDomain))
if(string.IsNullOrWhiteSpace(Website) && !string.IsNullOrWhiteSpace(node.WebDomain))
{
WebDomain = node.WebDomain;
var scheme = "http";
if((int)Build.VERSION.SdkInt >= 28)
{
scheme = node.WebScheme;
}
Website = string.Format("{0}://{1}", scheme, node.WebDomain);
}
}
}

View File

@@ -17,6 +17,7 @@ using Bit.Core.Enums;
using Android.Nfc;
using Bit.App.Utilities;
using System.Threading.Tasks;
using Android.Support.V4.Content;
namespace Bit.Droid
{
@@ -68,7 +69,7 @@ namespace Bit.Droid
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
UpdateTheme(ThemeManager.GetTheme());
UpdateTheme(ThemeManager.GetTheme(true));
base.OnCreate(savedInstanceState);
if(!CoreHelpers.InDebugMode())
{
@@ -202,9 +203,8 @@ namespace Bit.Droid
else
{
// camera
var root = new Java.IO.File(Android.OS.Environment.ExternalStorageDirectory, "bitwarden");
var file = new Java.IO.File(root, "temp_camera_photo.jpg");
uri = Android.Net.Uri.FromFile(file);
var file = new Java.IO.File(FilesDir, "temp_camera_photo.jpg");
uri = FileProvider.GetUriForFile(this, "com.x8bit.bitwarden.fileprovider", file);
fileName = $"photo_{DateTime.UtcNow.ToString("yyyyMMddHHmmss")}.jpg";
}

View File

@@ -15,6 +15,7 @@ using Bit.Droid.Services;
using Bit.Droid.Utilities;
using Plugin.CurrentActivity;
using Plugin.Fingerprint;
using Xamarin.Android.Net;
#if !FDROID
using Android.Gms.Security;
#endif
@@ -147,10 +148,10 @@ namespace Bit.Droid
private async Task BootstrapAsync()
{
var disableFavicon = await ServiceContainer.Resolve<IStorageService>("storageService").GetAsync<bool?>(
Constants.DisableFaviconKey);
await ServiceContainer.Resolve<IStateService>("stateService").SaveAsync(Constants.DisableFaviconKey,
disableFavicon);
var disableFavicon = await ServiceContainer.Resolve<IStorageService>("storageService")
.GetAsync<bool?>(Constants.DisableFaviconKey);
await ServiceContainer.Resolve<IStateService>("stateService").SaveAsync(
Constants.DisableFaviconKey, disableFavicon);
await ServiceContainer.Resolve<IEnvironmentService>("environmentService").SetUrlsFromStorageAsync();
}
}

View File

@@ -3,7 +3,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:versionCode="1"
android:versionName="2.0.2"
android:versionName="2.1.0"
package="com.x8bit.bitwarden">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="28" />

View File

@@ -23,7 +23,14 @@ namespace Bit.Droid.Renderers
var t = ResourcesCompat.GetDrawable(Resources, Resource.Drawable.slider_thumb, null);
if(t is GradientDrawable thumb)
{
thumb.SetColor(view.ThumbColor.ToAndroid());
if(view.ThumbColor == Color.Default)
{
thumb.SetColor(Color.White.ToAndroid());
}
else
{
thumb.SetColor(view.ThumbColor.ToAndroid());
}
thumb.SetStroke(3, view.ThumbBorderColor.ToAndroid());
Control.SetThumb(thumb);
}

View File

@@ -59,7 +59,7 @@
<item name="colorPrimary">@android:color/black</item>
<item name="colorPrimaryDark">@android:color/black</item>
<item name="colorControlNormal">@color/black_border</item>
<item name="android:navigationBarColor">@android:color/black</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
<!-- Nord theme -->

View File

@@ -48,6 +48,9 @@
<compatibility-package
android:name="org.mozilla.fenix"
android:maxLongVersionCode="10000000000"/>
<compatibility-package
android:name="org.mozilla.fenix.nightly"
android:maxLongVersionCode="10000000000"/>
<compatibility-package
android:name="org.mozilla.reference.browser"
android:maxLongVersionCode="10000000000"/>

View File

@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path name="cache" path="." />
<files-path name="internal" path="." />
</paths>

View File

@@ -1,5 +1,5 @@
<network-security-config>
<base-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<!-- Trust pre-installed CAs -->
<certificates src="system" />

View File

@@ -201,14 +201,14 @@ namespace Bit.Droid.Services
{
try
{
var root = new Java.IO.File(Android.OS.Environment.ExternalStorageDirectory, "bitwarden");
var file = new Java.IO.File(root, "temp_camera_photo.jpg");
var file = new Java.IO.File(activity.FilesDir, "temp_camera_photo.jpg");
if(!file.Exists())
{
file.ParentFile.Mkdirs();
file.CreateNewFile();
}
var outputFileUri = Android.Net.Uri.FromFile(file);
var outputFileUri = FileProvider.GetUriForFile(activity,
"com.x8bit.bitwarden.fileprovider", file);
additionalIntents.AddRange(GetCameraIntents(outputFileUri));
}
catch(Java.IO.IOException) { }

View File

@@ -54,6 +54,11 @@ namespace Bit.Droid.Services
netLanguage = "zh-Hans";
}
}
else if(androidLanguage.StartsWith("iw"))
{
// Uncomment when we support RTL
// netLanguage = "he";
}
else
{
// Certain languages need to be converted to CultureInfo equivalent

View File

@@ -51,6 +51,12 @@
<Compile Update="Pages\Generator\GeneratorHistoryPage.xaml.cs">
<DependentUpon>GeneratorHistoryPage.xaml</DependentUpon>
</Compile>
<Compile Update="Pages\Settings\AutofillPage.xaml.cs">
<DependentUpon>AutofillPage.xaml</DependentUpon>
</Compile>
<Compile Update="Pages\Settings\ExtensionPage.xaml.cs">
<DependentUpon>ExtensionPage.xaml</DependentUpon>
</Compile>
<Compile Update="Pages\Settings\AutofillServicePage.xaml.cs">
<DependentUpon>AutofillServicePage.xaml</DependentUpon>
</Compile>

View File

@@ -90,7 +90,16 @@ namespace Bit.App
else if(message.Command == "locked")
{
await _stateService.PurgeAsync();
var lockPage = new LockPage(_appOptions, !(message.Data as bool?).GetValueOrDefault());
var autoPromptFingerprint = !(message.Data as bool?).GetValueOrDefault();
if(autoPromptFingerprint && Device.RuntimePlatform == Device.iOS)
{
var lockOptions = await _storageService.GetAsync<int?>(Constants.LockOptionKey);
if(lockOptions == 0)
{
autoPromptFingerprint = false;
}
}
var lockPage = new LockPage(_appOptions, autoPromptFingerprint);
Device.BeginInvokeOnMainThread(() => Current.MainPage = new NavigationPage(lockPage));
}
else if(message.Command == "lockVault")
@@ -114,7 +123,7 @@ namespace Bit.App
{
if(Device.RuntimePlatform == Device.iOS)
{
SyncIfNeeded();
ResumedAsync();
}
}
else if(message.Command == "migrated")
@@ -153,6 +162,7 @@ namespace Bit.App
{
System.Diagnostics.Debug.WriteLine("XF App: OnStart");
await ClearCacheIfNeededAsync();
await TryClearCiphersCacheAsync();
Prime();
if(string.IsNullOrWhiteSpace(_appOptions.Uri))
{
@@ -176,16 +186,22 @@ namespace Bit.App
await HandleLockingAsync();
}
protected async override void OnResume()
protected override void OnResume()
{
System.Diagnostics.Debug.WriteLine("XF App: OnResume");
_messagingService.Send("cancelLockTimer");
await ClearCacheIfNeededAsync();
Prime();
if(Device.RuntimePlatform == Device.Android)
{
SyncIfNeeded();
ResumedAsync();
}
}
private async void ResumedAsync()
{
_messagingService.Send("cancelLockTimer");
await ClearCacheIfNeededAsync();
await TryClearCiphersCacheAsync();
Prime();
SyncIfNeeded();
if(Current.MainPage is NavigationPage navPage && navPage.CurrentPage is LockPage lockPage)
{
await lockPage.PromptFingerprintAfterResumeAsync();
@@ -213,7 +229,8 @@ namespace Bit.App
_folderService.ClearAsync(userId),
_collectionService.ClearAsync(userId),
_passwordGenerationService.ClearAsync(),
_lockService.ClearAsync());
_lockService.ClearAsync(),
_stateService.PurgeAsync());
_lockService.PinLocked = false;
_lockService.FingerprintLocked = true;
_searchService.ClearIndex();
@@ -316,7 +333,7 @@ namespace Bit.App
{
InitializeComponent();
SetCulture();
ThemeManager.SetTheme();
ThemeManager.SetTheme(Device.RuntimePlatform == Device.Android);
Current.MainPage = new HomePage();
var mainPageTask = SetMainPageAsync();
ServiceContainer.Resolve<MobilePlatformUtilsService>("platformUtilsService").Init();
@@ -341,5 +358,19 @@ namespace Bit.App
}
});
}
private async Task TryClearCiphersCacheAsync()
{
if(Device.RuntimePlatform != Device.iOS)
{
return;
}
var clearCache = await _storageService.GetAsync<bool?>(Constants.ClearCiphersCacheKey);
if(clearCache.GetValueOrDefault())
{
_cipherService.ClearCache();
await _storageService.RemoveAsync(Constants.ClearCiphersCacheKey);
}
}
}
}

View File

@@ -4,83 +4,102 @@
x:Class="Bit.App.Controls.CipherViewCell"
xmlns:controls="clr-namespace:Bit.App.Controls"
xmlns:ff="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms">
<Grid x:Name="_grid"
StyleClass="list-row, list-row-platform"
RowSpacing="0"
ColumnSpacing="0"
x:DataType="controls:CipherViewCellViewModel">
<Grid
x:Name="_grid"
StyleClass="list-row, list-row-platform"
RowSpacing="0"
ColumnSpacing="0"
x:DataType="controls:CipherViewCellViewModel">
<Grid.BindingContext>
<controls:CipherViewCellViewModel />
</Grid.BindingContext>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="60" />
</Grid.ColumnDefinitions>
<controls:FaLabel x:Name="_icon"
Grid.Column="0"
Grid.Row="0"
Grid.RowSpan="2"
HorizontalOptions="Center"
VerticalOptions="Center"
StyleClass="list-icon, list-icon-platform" />
<ff:CachedImage x:Name="_image"
Grid.Column="0"
Grid.Row="0"
Grid.RowSpan="2"
BitmapOptimizations="True"
ErrorPlaceholder="login.png"
HorizontalOptions="Center"
VerticalOptions="Center"
WidthRequest="22"
HeightRequest="22"
IsVisible="False"/>
<Label LineBreakMode="TailTruncation"
Grid.Column="1"
<controls:FaLabel
x:Name="_icon"
Grid.Row="0"
Grid.Column="0"
HorizontalOptions="Center"
VerticalOptions="Center"
StyleClass="list-icon, list-icon-platform" />
<ff:CachedImage
x:Name="_image"
Grid.Row="0"
Grid.Column="0"
BitmapOptimizations="True"
ErrorPlaceholder="login.png"
HorizontalOptions="Center"
VerticalOptions="Center"
WidthRequest="22"
HeightRequest="22"
IsVisible="False"/>
<Grid RowSpacing="0" ColumnSpacing="0" Grid.Row="0" Grid.Column="1" VerticalOptions="Center">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label
LineBreakMode="TailTruncation"
Grid.Column="0"
Grid.Row="0"
StyleClass="list-title, list-title-platform"
Text="{Binding Cipher.Name, Mode=OneWay}" />
<Label LineBreakMode="TailTruncation"
Grid.Column="1"
<Label
LineBreakMode="TailTruncation"
Grid.Column="0"
Grid.Row="1"
Grid.ColumnSpan="3"
StyleClass="list-subtitle, list-subtitle-platform"
Text="{Binding Cipher.SubTitle, Mode=OneWay}" />
<controls:FaLabel
Grid.Column="2"
Grid.Row="0"
HorizontalOptions="Start"
VerticalOptions="Center"
StyleClass="list-title-icon"
Margin="5, 0, 0, 0"
Text="&#xf1e0;"
IsVisible="{Binding Cipher.Shared, Mode=OneWay}" />
<controls:FaLabel
Grid.Column="3"
Grid.Row="0"
HorizontalOptions="Start"
VerticalOptions="Center"
StyleClass="list-title-icon"
Margin="5, 0, 0, 0"
Text="&#xf0c6;"
IsVisible="{Binding Cipher.HasAttachments, Mode=OneWay}" />
<controls:FaLabel
Grid.Column="1"
Grid.Row="0"
HorizontalOptions="Start"
VerticalOptions="Center"
StyleClass="list-title-icon"
Margin="5, 0, 0, 0"
Text="&#xf1e0;"
IsVisible="{Binding Cipher.Shared, Mode=OneWay}" />
<controls:FaLabel
Grid.Column="2"
Grid.Row="0"
HorizontalOptions="Start"
VerticalOptions="Center"
StyleClass="list-title-icon"
Margin="5, 0, 0, 0"
Text="&#xf0c6;"
IsVisible="{Binding Cipher.HasAttachments, Mode=OneWay}" />
</Grid>
<controls:MiButton
Text="&#xe5d4;"
StyleClass="list-row-button, list-row-button-platform, btn-disabled"
Clicked="ImageButton_Clicked"
Grid.Column="4"
Grid.Row="0"
Grid.RowSpan="2" />
Grid.Column="2"
Text="&#xe5d3;"
StyleClass="list-row-button, list-row-button-platform, btn-disabled"
Clicked="MoreButton_Clicked"
VerticalOptions="CenterAndExpand"
HorizontalOptions="EndAndExpand" />
</Grid>
</ViewCell>

View File

@@ -181,7 +181,7 @@ namespace Bit.App.Controls
return new Tuple<string, string>(icon, image);
}
private void ImageButton_Clicked(object sender, EventArgs e)
private void MoreButton_Clicked(object sender, EventArgs e)
{
ButtonCommand?.Execute(Cipher);
}

View File

@@ -107,6 +107,10 @@ namespace Bit.App.Migration
// await storageService.SaveAsync(Constants.PushLastRegistrationDateKey, lastReg);
await storageService.SaveAsync("rememberedEmail",
settingsShim.GetValueOrDefault("other:lastLoginEmail", null));
await storageService.SaveAsync("appExtensionStarted",
settingsShim.GetValueOrDefault("extension:started", false));
await storageService.SaveAsync("appExtensionActivated",
settingsShim.GetValueOrDefault("extension:activated", false));
await environmentService.SetUrlsAsync(new Core.Models.Data.EnvironmentUrlData
{

View File

@@ -4,64 +4,119 @@ namespace Bit.App.Migration
{
public class SettingsShim
{
private readonly string _sharedName;
public SettingsShim(string sharedName = null)
{
_sharedName = sharedName;
}
public bool Contains(string key)
{
return Xamarin.Essentials.Preferences.ContainsKey(key);
return _sharedName != null ? Xamarin.Essentials.Preferences.ContainsKey(key, _sharedName) :
Xamarin.Essentials.Preferences.ContainsKey(key);
}
public string GetValueOrDefault(string key, string defaultValue)
{
return Xamarin.Essentials.Preferences.Get(key, defaultValue);
return _sharedName != null ? Xamarin.Essentials.Preferences.Get(key, defaultValue, _sharedName) :
Xamarin.Essentials.Preferences.Get(key, defaultValue);
}
public DateTime GetValueOrDefault(string key, DateTime defaultValue)
{
return Xamarin.Essentials.Preferences.Get(key, defaultValue);
return _sharedName != null ? Xamarin.Essentials.Preferences.Get(key, defaultValue, _sharedName) :
Xamarin.Essentials.Preferences.Get(key, defaultValue);
}
public bool GetValueOrDefault(string key, bool defaultValue)
{
return Xamarin.Essentials.Preferences.Get(key, defaultValue);
return _sharedName != null ? Xamarin.Essentials.Preferences.Get(key, defaultValue, _sharedName) :
Xamarin.Essentials.Preferences.Get(key, defaultValue);
}
public int GetValueOrDefault(string key, int defaultValue)
{
return Xamarin.Essentials.Preferences.Get(key, defaultValue);
return _sharedName != null ? Xamarin.Essentials.Preferences.Get(key, defaultValue, _sharedName) :
Xamarin.Essentials.Preferences.Get(key, defaultValue);
}
public long GetValueOrDefault(string key, long defaultValue)
{
return Xamarin.Essentials.Preferences.Get(key, defaultValue);
return _sharedName != null ? Xamarin.Essentials.Preferences.Get(key, defaultValue, _sharedName) :
Xamarin.Essentials.Preferences.Get(key, defaultValue);
}
public void AddOrUpdateValue(string key, string value)
{
Xamarin.Essentials.Preferences.Set(key, value);
if(_sharedName != null)
{
Xamarin.Essentials.Preferences.Set(key, value, _sharedName);
}
else
{
Xamarin.Essentials.Preferences.Set(key, value);
}
}
public void AddOrUpdateValue(string key, DateTime value)
{
Xamarin.Essentials.Preferences.Set(key, value);
if(_sharedName != null)
{
Xamarin.Essentials.Preferences.Set(key, value, _sharedName);
}
else
{
Xamarin.Essentials.Preferences.Set(key, value);
}
}
public void AddOrUpdateValue(string key, bool value)
{
Xamarin.Essentials.Preferences.Set(key, value);
if(_sharedName != null)
{
Xamarin.Essentials.Preferences.Set(key, value, _sharedName);
}
else
{
Xamarin.Essentials.Preferences.Set(key, value);
}
}
public void AddOrUpdateValue(string key, long value)
{
Xamarin.Essentials.Preferences.Set(key, value);
if(_sharedName != null)
{
Xamarin.Essentials.Preferences.Set(key, value, _sharedName);
}
else
{
Xamarin.Essentials.Preferences.Set(key, value);
}
}
public void AddOrUpdateValue(string key, int value)
{
Xamarin.Essentials.Preferences.Set(key, value);
if(_sharedName != null)
{
Xamarin.Essentials.Preferences.Set(key, value, _sharedName);
}
else
{
Xamarin.Essentials.Preferences.Set(key, value);
}
}
public void Remove(string key)
{
Xamarin.Essentials.Preferences.Remove(key);
if(_sharedName != null)
{
Xamarin.Essentials.Preferences.Remove(key, _sharedName);
}
else
{
Xamarin.Essentials.Preferences.Remove(key);
}
}
}
}

View File

@@ -21,7 +21,7 @@
<StackLayout Spacing="20">
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n SelfHostedEnvironment}"
<Label Text="{u:I18n SelfHostedEnvironment, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<StackLayout StyleClass="box-row">
@@ -42,7 +42,7 @@
</StackLayout>
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n CustomEnvironment}"
<Label Text="{u:I18n CustomEnvironment, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<StackLayout StyleClass="box-row">

View File

@@ -1,14 +1,19 @@
using System;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using System;
using Xamarin.Forms;
namespace Bit.App.Pages
{
public partial class EnvironmentPage : BaseContentPage
{
private EnvironmentPageViewModel _vm;
private readonly IMessagingService _messagingService;
private readonly EnvironmentPageViewModel _vm;
public EnvironmentPage()
{
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_messagingService.Send("showStatusBar", true);
InitializeComponent();
_vm = BindingContext as EnvironmentPageViewModel;
_vm.Page = this;
@@ -33,10 +38,11 @@ namespace Bit.App.Pages
}
}
private async void Close_Clicked(object sender, System.EventArgs e)
private async void Close_Clicked(object sender, EventArgs e)
{
if(DoOnce())
{
_messagingService.Send("showStatusBar", false);
await Navigation.PopModalAsync();
}
}

View File

@@ -16,7 +16,14 @@
<controls:FaButton Text="&#xf013;"
StyleClass="btn-muted, btn-icon, btn-icon-platform"
HorizontalOptions="Start"
Clicked="Settings_Clicked" />
Clicked="Settings_Clicked">
<controls:FaButton.Margin>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS" Value="0, 10, 0, 0" />
<On Platform="Android" Value="0" />
</OnPlatform>
</controls:FaButton.Margin>
</controls:FaButton>
<StackLayout VerticalOptions="CenterAndExpand" Spacing="20">
<Image
x:Name="_logo"

View File

@@ -1,4 +1,6 @@
using Bit.App.Utilities;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using System;
using System.Threading.Tasks;
using Xamarin.Forms;
@@ -7,10 +9,14 @@ namespace Bit.App.Pages
{
public partial class HomePage : BaseContentPage
{
private IMessagingService _messagingService;
public HomePage()
{
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_messagingService.Send("showStatusBar", false);
InitializeComponent();
var theme = ThemeManager.GetTheme();
var theme = ThemeManager.GetTheme(Device.RuntimePlatform == Device.Android);
var darkbasedTheme = theme == "dark" || theme == "black" || theme == "nord";
_logo.Source = darkbasedTheme ? "logo_white.png" : "logo.png";
}
@@ -21,6 +27,12 @@ namespace Bit.App.Pages
await Navigation.PushModalAsync(new NavigationPage(new LoginPage(email)));
}
protected override void OnAppearing()
{
base.OnAppearing();
_messagingService.Send("showStatusBar", false);
}
private void LogIn_Clicked(object sender, EventArgs e)
{
if(DoOnce())

View File

@@ -45,6 +45,8 @@
Text="{Binding Pin}"
StyleClass="box-value"
Keyboard="Numeric"
IsSpellCheckEnabled="False"
IsTextPredictionEnabled="False"
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
Grid.Row="1"
Grid.Column="0"
@@ -76,6 +78,8 @@
x:Name="_masterPassword"
Text="{Binding MasterPassword}"
StyleClass="box-value"
IsSpellCheckEnabled="False"
IsTextPredictionEnabled="False"
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
Grid.Row="1"
Grid.Column="0"

View File

@@ -21,7 +21,7 @@ namespace Bit.App.Pages
InitializeComponent();
_vm = BindingContext as LockPageViewModel;
_vm.Page = this;
_vm.UnlockedAction = () =>
_vm.UnlockedAction = () => Device.BeginInvokeOnMainThread(() =>
{
if(_appOptions != null)
{
@@ -37,7 +37,7 @@ namespace Bit.App.Pages
}
}
Application.Current.MainPage = new TabsPage(_appOptions);
};
});
MasterPasswordEntry = _masterPassword;
PinEntry = _pin;
}
@@ -87,10 +87,7 @@ namespace Bit.App.Pages
var tasks = Task.Run(async () =>
{
await Task.Delay(50);
Device.BeginInvokeOnMainThread(async () =>
{
await _vm.SubmitAsync();
});
Device.BeginInvokeOnMainThread(async () => await _vm.SubmitAsync());
});
}
}

View File

@@ -23,6 +23,7 @@ namespace Bit.App.Pages
private readonly IMessagingService _messagingService;
private readonly IStorageService _secureStorageService;
private readonly IEnvironmentService _environmentService;
private readonly IStateService _stateService;
private bool _hasKey;
private string _email;
@@ -46,6 +47,7 @@ namespace Bit.App.Pages
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_secureStorageService = ServiceContainer.Resolve<IStorageService>("secureStorageService");
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
PageTitle = AppResources.VerifyMasterPassword;
TogglePasswordCommand = new Command(TogglePassword);
@@ -174,7 +176,7 @@ namespace Bit.App.Pages
if(!failed)
{
Pin = string.Empty;
DoContinue();
await DoContinueAsync();
}
}
else
@@ -270,7 +272,7 @@ namespace Bit.App.Pages
_lockService.FingerprintLocked = !success;
if(success)
{
DoContinue();
await DoContinueAsync();
}
}
@@ -280,11 +282,13 @@ namespace Bit.App.Pages
{
await _cryptoService.SetKeyAsync(key);
}
DoContinue();
await DoContinueAsync();
}
private void DoContinue()
private async Task DoContinueAsync()
{
var disableFavicon = await _storageService.GetAsync<bool?>(Constants.DisableFaviconKey);
await _stateService.SaveAsync(Constants.DisableFaviconKey, disableFavicon.GetValueOrDefault());
_messagingService.Send("unlocked");
UnlockedAction?.Invoke();
}

View File

@@ -55,6 +55,8 @@
x:Name="_masterPassword"
Text="{Binding MasterPassword}"
StyleClass="box-value"
IsSpellCheckEnabled="False"
IsTextPredictionEnabled="False"
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
Grid.Row="1"
Grid.Column="0"

View File

@@ -1,14 +1,19 @@
using System;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using System;
using Xamarin.Forms;
namespace Bit.App.Pages
{
public partial class LoginPage : BaseContentPage
{
private LoginPageViewModel _vm;
private readonly IMessagingService _messagingService;
private readonly LoginPageViewModel _vm;
public LoginPage(string email = null)
{
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_messagingService.Send("showStatusBar", true);
InitializeComponent();
_vm = BindingContext as LoginPageViewModel;
_vm.Page = this;
@@ -55,10 +60,11 @@ namespace Bit.App.Pages
}
}
private async void Close_Clicked(object sender, System.EventArgs e)
private async void Close_Clicked(object sender, EventArgs e)
{
if(DoOnce())
{
_messagingService.Send("showStatusBar", false);
await Navigation.PopModalAsync();
}
}

View File

@@ -1,5 +1,6 @@
using Bit.App.Abstractions;
using Bit.App.Resources;
using Bit.Core;
using Bit.Core.Abstractions;
using Bit.Core.Exceptions;
using Bit.Core.Utilities;
@@ -18,6 +19,7 @@ namespace Bit.App.Pages
private readonly ISyncService _syncService;
private readonly IStorageService _storageService;
private readonly IPlatformUtilsService _platformUtilsService;
private readonly IStateService _stateService;
private bool _showPassword;
private string _email;
@@ -30,6 +32,7 @@ namespace Bit.App.Pages
_syncService = ServiceContainer.Resolve<ISyncService>("syncService");
_storageService = ServiceContainer.Resolve<IStorageService>("storageService");
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
PageTitle = AppResources.Bitwarden;
TogglePasswordCommand = new Command(TogglePassword);
@@ -123,6 +126,8 @@ namespace Bit.App.Pages
}
else
{
var disableFavicon = await _storageService.GetAsync<bool?>(Constants.DisableFaviconKey);
await _stateService.SaveAsync(Constants.DisableFaviconKey, disableFavicon.GetValueOrDefault());
var task = Task.Run(async () => await _syncService.FullSyncAsync(true));
Application.Current.MainPage = new TabsPage();
}

View File

@@ -55,6 +55,8 @@
x:Name="_masterPassword"
Text="{Binding MasterPassword}"
StyleClass="box-value"
IsSpellCheckEnabled="False"
IsTextPredictionEnabled="False"
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
Grid.Row="1"
Grid.Column="0" />
@@ -89,6 +91,8 @@
x:Name="_confirmMasterPassword"
Text="{Binding ConfirmMasterPassword}"
StyleClass="box-value"
IsSpellCheckEnabled="False"
IsTextPredictionEnabled="False"
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
Grid.Row="1"
Grid.Column="0" />

View File

@@ -1,14 +1,19 @@
using System;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using System;
using Xamarin.Forms;
namespace Bit.App.Pages
{
public partial class RegisterPage : BaseContentPage
{
private RegisterPageViewModel _vm;
private readonly IMessagingService _messagingService;
private readonly RegisterPageViewModel _vm;
public RegisterPage(HomePage homePage)
{
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_messagingService.Send("showStatusBar", true);
InitializeComponent();
_vm = BindingContext as RegisterPageViewModel;
_vm.Page = this;
@@ -51,10 +56,11 @@ namespace Bit.App.Pages
}
}
private async void Close_Clicked(object sender, System.EventArgs e)
private async void Close_Clicked(object sender, EventArgs e)
{
if(DoOnce())
{
_messagingService.Send("showStatusBar", false);
await Navigation.PopModalAsync();
}
}

View File

@@ -13,19 +13,20 @@
<pages:TwoFactorPageViewModel />
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Text="{u:I18n Cancel}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
x:Name="_cancelItem" />
<ToolbarItem Text="{u:I18n Continue}" Clicked="Continue_Clicked" Order="Primary"
x:Name="_continueItem" />
</ContentPage.ToolbarItems>
<ContentPage.Resources>
<ResourceDictionary>
<u:InverseBoolConverter x:Key="inverseBool" />
<u:IsNullConverter x:Key="isNull" />
<ToolbarItem Text="{u:I18n Continue}" Clicked="Continue_Clicked"
x:Name="_continueItem" x:Key="continueItem" />
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.ToolbarItems>
<ToolbarItem Text="{u:I18n Cancel}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
</ContentPage.ToolbarItems>
<ScrollView x:Name="_scrollView">
<StackLayout Spacing="10" Padding="0, 0, 0, 10" VerticalOptions="FillAndExpand">
<StackLayout Spacing="20" Padding="0" IsVisible="{Binding TotpMethod, Mode=OneWay}">
@@ -123,6 +124,10 @@
IsVisible="{Binding EmailMethod}"
Clicked="ResendEmail_Clicked"
Margin="10, 0"></Button>
<Button Text="{u:I18n TryAgain}"
IsVisible="{Binding ShowTryAgain}"
Clicked="TryAgain_Clicked"
Margin="10, 0"></Button>
<Button Text="{u:I18n UseAnotherTwoStepMethod}"
Clicked="Methods_Clicked"
Margin="10, 0"></Button>

View File

@@ -26,7 +26,7 @@ namespace Bit.App.Pages
DuoWebView = _duoWebView;
if(Device.RuntimePlatform == Device.Android)
{
ToolbarItems.RemoveAt(0);
ToolbarItems.Remove(_cancelItem);
}
}
@@ -34,7 +34,7 @@ namespace Bit.App.Pages
public void AddContinueButton()
{
if(ToolbarItems.Count == 0)
if(!ToolbarItems.Contains(_continueItem))
{
ToolbarItems.Add(_continueItem);
}
@@ -42,7 +42,7 @@ namespace Bit.App.Pages
public void RemoveContinueButton()
{
if(ToolbarItems.Count > 0)
if(ToolbarItems.Contains(_continueItem))
{
ToolbarItems.Remove(_continueItem);
}
@@ -55,11 +55,13 @@ namespace Bit.App.Pages
{
if(message.Command == "gotYubiKeyOTP")
{
if(_vm.YubikeyMethod)
var token = (string)message.Data;
if(_vm.YubikeyMethod && !string.IsNullOrWhiteSpace(token) &&
token.Length > 40 && !token.Contains(" "))
{
Device.BeginInvokeOnMainThread(async () =>
{
_vm.Token = (string)message.Data;
_vm.Token = token;
await _vm.SubmitAsync();
});
}
@@ -138,5 +140,16 @@ namespace Bit.App.Pages
await Navigation.PopModalAsync();
}
}
private void TryAgain_Clicked(object sender, EventArgs e)
{
if(DoOnce())
{
if(_vm.YubikeyMethod)
{
_messagingService.Send("listenYubiKeyOTP", true);
}
}
}
}
}

View File

@@ -1,5 +1,6 @@
using Bit.App.Abstractions;
using Bit.App.Resources;
using Bit.Core;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
@@ -23,6 +24,7 @@ namespace Bit.App.Pages
private readonly IEnvironmentService _environmentService;
private readonly IMessagingService _messagingService;
private readonly IBroadcasterService _broadcasterService;
private readonly IStateService _stateService;
private bool _u2fSupported = false;
private TwoFactorProviderType? _selectedProviderType;
@@ -40,6 +42,7 @@ namespace Bit.App.Pages
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
PageTitle = AppResources.TwoStepLogin;
SubmitCommand = new Command(async () => await SubmitAsync());
@@ -66,6 +69,8 @@ namespace Bit.App.Pages
public bool TotpMethod => AuthenticatorMethod || EmailMethod;
public bool ShowTryAgain => YubikeyMethod && Device.RuntimePlatform == Device.iOS;
public string YubikeyInstruction => Device.RuntimePlatform == Device.iOS ? AppResources.YubiKeyInstructionIos :
AppResources.YubiKeyInstruction;
@@ -79,6 +84,7 @@ namespace Bit.App.Pages
nameof(YubikeyMethod),
nameof(AuthenticatorMethod),
nameof(TotpMethod),
nameof(ShowTryAgain),
});
}
public Command SubmitCommand { get; }
@@ -157,7 +163,7 @@ namespace Bit.App.Pages
{
_messagingService.Send("listenYubiKeyOTP", false);
}
if(DuoMethod)
if(SelectedProviderType == null || DuoMethod)
{
page.RemoveContinueButton();
}
@@ -200,6 +206,8 @@ namespace Bit.App.Pages
var task = Task.Run(() => _syncService.FullSyncAsync(true));
_messagingService.Send("listenYubiKeyOTP", false);
_broadcasterService.Unsubscribe(nameof(TwoFactorPage));
var disableFavicon = await _storageService.GetAsync<bool?>(Constants.DisableFaviconKey);
await _stateService.SaveAsync(Constants.DisableFaviconKey, disableFavicon.GetValueOrDefault());
Application.Current.MainPage = new TabsPage();
}
catch(ApiException e)

View File

@@ -11,8 +11,8 @@ namespace Bit.App.Pages
{
private IStorageService _storageService;
protected int AndroidShowModalAnimationDelay = 400;
protected int AndroidShowPageAnimationDelay = 100;
protected int ShowModalAnimationDelay = 400;
protected int ShowPageAnimationDelay = 100;
public DateTime? LastPageAction { get; set; }
@@ -77,21 +77,16 @@ namespace Bit.App.Pages
}
await Task.Run(async () =>
{
await Task.Delay(fromModal ? AndroidShowModalAnimationDelay : AndroidShowPageAnimationDelay);
await Task.Delay(fromModal ? ShowModalAnimationDelay : ShowPageAnimationDelay);
Device.BeginInvokeOnMainThread(async () => await DoWorkAsync());
});
}
protected void RequestFocus(InputView input)
{
if(Device.RuntimePlatform == Device.iOS)
{
input.Focus();
return;
}
Task.Run(async () =>
{
await Task.Delay(AndroidShowModalAnimationDelay);
await Task.Delay(ShowModalAnimationDelay);
Device.BeginInvokeOnMainThread(() => input.Focus());
});
}

View File

@@ -19,17 +19,22 @@
<ResourceDictionary>
<u:InverseBoolConverter x:Key="inverseBool" />
<u:DateTimeConverter x:Key="dateTime" />
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
x:Name="_closeItem" x:Key="closeItem" />
<ToolbarItem Text="{u:I18n Clear}"
Clicked="Clear_Clicked"
Order="Secondary"
x:Name="_clearItem"
x:Key="clearItem" />
<ToolbarItem Icon="more_vert.png"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n Options}"
Clicked="More_Clicked"
x:Name="_moreItem"
x:Key="moreItem" />
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.ToolbarItems>
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
<ToolbarItem Text="{u:I18n Clear}"
Clicked="Clear_Clicked"
Order="Secondary"
x:Name="_clearItem" />
</ContentPage.ToolbarItems>
<StackLayout x:Name="_mainLayout">
<Label IsVisible="{Binding ShowNoData}"
Text="{u:I18n NoPasswordsToList}"

View File

@@ -1,4 +1,6 @@
using System;
using Bit.App.Resources;
using System;
using Xamarin.Forms;
namespace Bit.App.Pages
{
@@ -12,6 +14,15 @@ namespace Bit.App.Pages
SetActivityIndicator();
_vm = BindingContext as GeneratorHistoryPageViewModel;
_vm.Page = this;
if(Device.RuntimePlatform == Device.iOS)
{
ToolbarItems.Add(_closeItem);
ToolbarItems.Add(_moreItem);
}
else
{
ToolbarItems.Add(_clearItem);
}
}
protected override async void OnAppearing()
@@ -34,5 +45,19 @@ namespace Bit.App.Pages
await Navigation.PopModalAsync();
}
}
private async void More_Clicked(object sender, EventArgs e)
{
if(!DoOnce())
{
return;
}
var selection = await DisplayActionSheet(AppResources.Options, AppResources.Cancel,
null, AppResources.Clear);
if(selection == AppResources.Clear)
{
await _vm.ClearAsync();
}
}
}
}

View File

@@ -12,19 +12,27 @@
<pages:GeneratorPageViewModel />
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Text="{u:I18n Select}"
Clicked="Select_Clicked"
Order="Primary"
x:Name="_selectItem" />
<ToolbarItem Text="{u:I18n PasswordHistory}"
Clicked="History_Clicked"
Order="Secondary" />
</ContentPage.ToolbarItems>
<ContentPage.Resources>
<ResourceDictionary>
<u:InverseBoolConverter x:Key="inverseBool" />
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
x:Name="_closeItem" x:Key="closeItem" />
<ToolbarItem Text="{u:I18n Select}"
Clicked="Select_Clicked"
Order="Primary"
x:Name="_selectItem"
x:Key="selectItem" />
<ToolbarItem Text="{u:I18n PasswordHistory}"
Clicked="History_Clicked"
Order="Secondary"
x:Name="_historyItem"
x:Key="historyItem" />
<ToolbarItem Icon="more_vert.png"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n Options}"
Clicked="More_Clicked"
x:Name="_moreItem"
x:Key="moreItem" />
</ResourceDictionary>
</ContentPage.Resources>
@@ -46,7 +54,7 @@
</StackLayout>
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n Options}"
<Label Text="{u:I18n Options, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<StackLayout StyleClass="box-row, box-row-input">
@@ -54,6 +62,7 @@
Text="{u:I18n Type}"
StyleClass="box-label" />
<Picker
x:Name="_typePicker"
ItemsSource="{Binding TypeOptions, Mode=OneTime}"
SelectedIndex="{Binding TypeSelectedIndex}"
StyleClass="box-value" />
@@ -87,8 +96,31 @@
StyleClass="box-label" />
<Entry
Text="{Binding WordSeparator}"
IsSpellCheckEnabled="False"
IsTextPredictionEnabled="False"
StyleClass="box-value" />
</StackLayout>
<StackLayout StyleClass="box-row, box-row-switch">
<Label
Text="{u:I18n Capitalize}"
StyleClass="box-label, box-label-regular"
HorizontalOptions="StartAndExpand" />
<Switch
IsToggled="{Binding Capitalize}"
StyleClass="box-value"
HorizontalOptions="End" />
</StackLayout>
<BoxView StyleClass="box-row-separator" />
<StackLayout StyleClass="box-row, box-row-switch">
<Label
Text="{u:I18n IncludeNumber}"
StyleClass="box-label, box-label-regular"
HorizontalOptions="StartAndExpand" />
<Switch
IsToggled="{Binding IncludeNumber}"
StyleClass="box-value"
HorizontalOptions="End" />
</StackLayout>
</StackLayout>
<StackLayout Spacing="0" Padding="0" IsVisible="{Binding IsPassword}">
<StackLayout StyleClass="box-row, box-row-slider">

View File

@@ -1,6 +1,9 @@
using System;
using Bit.App.Resources;
using System;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
namespace Bit.App.Pages
{
@@ -19,9 +22,29 @@ namespace Bit.App.Pages
_vm.Page = this;
_fromTabPage = fromTabPage;
_selectAction = selectAction;
if(selectAction == null)
var isIos = Device.RuntimePlatform == Device.iOS;
if(selectAction != null)
{
ToolbarItems.Remove(_selectItem);
if(isIos)
{
ToolbarItems.Add(_closeItem);
}
ToolbarItems.Add(_selectItem);
}
else
{
if(isIos)
{
ToolbarItems.Add(_moreItem);
}
else
{
ToolbarItems.Add(_historyItem);
}
}
if(isIos)
{
_typePicker.On<iOS>().SetUpdateMode(UpdateMode.WhenFinished);
}
}
@@ -59,6 +82,21 @@ namespace Bit.App.Pages
await _vm.CopyAsync();
}
private async void More_Clicked(object sender, EventArgs e)
{
if(!DoOnce())
{
return;
}
var selection = await DisplayActionSheet(AppResources.Options, AppResources.Cancel,
null, AppResources.PasswordHistory);
if(selection == AppResources.PasswordHistory)
{
var page = new GeneratorHistoryPage();
await Navigation.PushModalAsync(new Xamarin.Forms.NavigationPage(page));
}
}
private void Select_Clicked(object sender, EventArgs e)
{
_selectAction?.Invoke(_vm.Password);
@@ -67,12 +105,20 @@ namespace Bit.App.Pages
private async void History_Clicked(object sender, EventArgs e)
{
var page = new GeneratorHistoryPage();
await Navigation.PushModalAsync(new NavigationPage(page));
await Navigation.PushModalAsync(new Xamarin.Forms.NavigationPage(page));
}
private async void LengthSlider_DragCompleted(object sender, EventArgs e)
{
await _vm.SliderChangedAsync();
}
private async void Close_Clicked(object sender, EventArgs e)
{
if(DoOnce())
{
await Navigation.PopModalAsync();
}
}
}
}

View File

@@ -3,9 +3,7 @@ using Bit.App.Utilities;
using Bit.Core.Abstractions;
using Bit.Core.Models.Domain;
using Bit.Core.Utilities;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Xamarin.Forms;
@@ -29,6 +27,8 @@ namespace Bit.App.Pages
private int _length = 5;
private int _numWords = 3;
private string _wordSeparator;
private bool _capitalize;
private bool _includeNumber;
private int _typeSelectedIndex;
private bool _doneIniting;
@@ -196,6 +196,32 @@ namespace Bit.App.Pages
}
}
public bool Capitalize
{
get => _capitalize;
set
{
if(SetProperty(ref _capitalize, value))
{
_options.Capitalize = value;
var task = SaveOptionsAsync();
}
}
}
public bool IncludeNumber
{
get => _includeNumber;
set
{
if(SetProperty(ref _includeNumber, value))
{
_options.Number = value;
var task = SaveOptionsAsync();
}
}
}
public int TypeSelectedIndex
{
get => _typeSelectedIndex;
@@ -273,6 +299,8 @@ namespace Bit.App.Pages
Uppercase = _options.Uppercase.GetValueOrDefault();
Lowercase = _options.Lowercase.GetValueOrDefault();
Length = _options.Length.GetValueOrDefault(5);
Capitalize = _options.Capitalize.GetValueOrDefault();
IncludeNumber = _options.IncludeNumber.GetValueOrDefault();
}
private void SetOptions()
@@ -288,6 +316,8 @@ namespace Bit.App.Pages
_options.Uppercase = Uppercase;
_options.Lowercase = Lowercase;
_options.Length = Length;
_options.Capitalize = Capitalize;
_options.IncludeNumber = IncludeNumber;
}
}
}

View File

@@ -0,0 +1,48 @@
<?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.AutofillPage"
xmlns:pages="clr-namespace:Bit.App.Pages"
xmlns:u="clr-namespace:Bit.App.Utilities"
Title="{u:I18n PasswordAutofill}">
<ContentPage.ToolbarItems>
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
</ContentPage.ToolbarItems>
<ScrollView>
<StackLayout Spacing="5"
Padding="20, 20, 20, 30"
VerticalOptions="FillAndExpand">
<Label Text="{u:I18n ExtensionInstantAccess}"
HorizontalOptions="Center"
HorizontalTextAlignment="Center"
LineBreakMode="WordWrap"
StyleClass="text-lg"
Margin="0, 0, 0, 15" />
<Label Text="{u:I18n AutofillTurnOn}"
HorizontalOptions="Center"
HorizontalTextAlignment="Center"
LineBreakMode="WordWrap"
Margin="0, 0, 0, 15" />
<Label Text="{u:I18n AutofillTurnOn1}"
LineBreakMode="WordWrap" />
<Label Text="{u:I18n AutofillTurnOn2}"
LineBreakMode="WordWrap" />
<Label Text="{u:I18n AutofillTurnOn3}"
LineBreakMode="WordWrap" />
<Label Text="{u:I18n AutofillTurnOn4}"
LineBreakMode="WordWrap" />
<Label Text="{u:I18n AutofillTurnOn5}"
LineBreakMode="WordWrap" />
<Image Source="autofill-kb.png"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center"
Margin="0, 10, 0, 0"
WidthRequest="290"
HeightRequest="252" />
</StackLayout>
</ScrollView>
</pages:BaseContentPage>

View File

@@ -0,0 +1,20 @@
using System;
namespace Bit.App.Pages
{
public partial class AutofillPage : BaseContentPage
{
public AutofillPage()
{
InitializeComponent();
}
private void Close_Clicked(object sender, EventArgs e)
{
if(DoOnce())
{
Navigation.PopModalAsync();
}
}
}
}

View File

@@ -0,0 +1,95 @@
<?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.ExtensionPage"
xmlns:pages="clr-namespace:Bit.App.Pages"
xmlns:u="clr-namespace:Bit.App.Utilities"
x:DataType="pages:ExtensionPageViewModel"
Title="{Binding PageTitle}">
<ContentPage.BindingContext>
<pages:ExtensionPageViewModel />
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
</ContentPage.ToolbarItems>
<ScrollView>
<StackLayout Padding="0" Spacing="0" VerticalOptions="FillAndExpand">
<StackLayout Spacing="20"
Padding="20, 20, 20, 30"
VerticalOptions="FillAndExpand"
IsVisible="{Binding NotStarted}">
<Label Text="{u:I18n ExtensionInstantAccess}"
StyleClass="text-lg"
HorizontalOptions="Center"
HorizontalTextAlignment="Center"
LineBreakMode="WordWrap" />
<Label Text="{u:I18n ExtensionTurnOn}"
HorizontalOptions="Center"
HorizontalTextAlignment="Center"
LineBreakMode="WordWrap" />
<Image Source="ext-more.png"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center"
Margin="0, -10, 0, 0"
WidthRequest="290"
HeightRequest="252" />
<Button Text="{u:I18n ExtensionEnable}"
Clicked="Show_Clicked"
VerticalOptions="End"
HorizontalOptions="Fill" />
</StackLayout>
<StackLayout Spacing="20"
Padding="20, 20, 20, 30"
VerticalOptions="FillAndExpand"
IsVisible="{Binding StartedAndNotActivated}">
<Label Text="{u:I18n ExtensionAlmostDone}"
StyleClass="text-lg"
HorizontalOptions="Center"
HorizontalTextAlignment="Center"
LineBreakMode="WordWrap" />
<Label Text="{u:I18n ExtensionTapIcon}"
HorizontalOptions="Center"
HorizontalTextAlignment="Center"
LineBreakMode="WordWrap" />
<Image Source="ext-act.png"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center"
Margin="0, -10, 0, 0"
WidthRequest="290"
HeightRequest="252" />
<Button Text="{u:I18n ExtensionEnable}"
Clicked="Show_Clicked"
VerticalOptions="End"
HorizontalOptions="Fill" />
</StackLayout>
<StackLayout Spacing="20"
Padding="20, 20, 20, 30"
VerticalOptions="FillAndExpand"
IsVisible="{Binding StartedAndActivated}">
<Label Text="{u:I18n ExtensionReady}"
StyleClass="text-lg"
HorizontalOptions="Center"
HorizontalTextAlignment="Center"
LineBreakMode="WordWrap" />
<Label Text="{u:I18n ExtensionInSafari}"
HorizontalOptions="Center"
HorizontalTextAlignment="Center"
LineBreakMode="WordWrap" />
<Image Source="ext-use.png"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center"
Margin="0, -10, 0, 0"
WidthRequest="290"
HeightRequest="252" />
<Button Text="{u:I18n ExntesionReenable}"
Clicked="Show_Clicked"
VerticalOptions="End"
HorizontalOptions="Fill" />
</StackLayout>
</StackLayout>
</ScrollView>
</pages:BaseContentPage>

View File

@@ -0,0 +1,38 @@
using System;
namespace Bit.App.Pages
{
public partial class ExtensionPage : BaseContentPage
{
private readonly ExtensionPageViewModel _vm;
public ExtensionPage()
{
InitializeComponent();
_vm = BindingContext as ExtensionPageViewModel;
_vm.Page = this;
}
protected async override void OnAppearing()
{
base.OnAppearing();
await _vm.InitAsync();
}
private void Show_Clicked(object sender, EventArgs e)
{
if(DoOnce())
{
_vm.ShowExtension();
}
}
private void Close_Clicked(object sender, EventArgs e)
{
if(DoOnce())
{
Navigation.PopModalAsync();
}
}
}
}

View File

@@ -0,0 +1,75 @@
using Bit.App.Resources;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using System.Threading.Tasks;
namespace Bit.App.Pages
{
public class ExtensionPageViewModel : BaseViewModel
{
private const string StartedKey = "appExtensionStarted";
private const string ActivatedKey = "appExtensionActivated";
private readonly IMessagingService _messagingService;
private readonly IStorageService _storageService;
private readonly IPlatformUtilsService _platformUtilsService;
private bool _started;
private bool _activated;
public ExtensionPageViewModel()
{
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
_storageService = ServiceContainer.Resolve<IStorageService>("storageService");
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
PageTitle = AppResources.AppExtension;
}
public bool Started
{
get => _started;
set => SetProperty(ref _started, value, additionalPropertyNames: new string[]
{
nameof(NotStarted),
nameof(StartedAndNotActivated),
nameof(StartedAndActivated)
});
}
public bool Activated
{
get => _activated;
set => SetProperty(ref _activated, value, additionalPropertyNames: new string[]
{
nameof(StartedAndNotActivated),
nameof(StartedAndActivated)
});
}
public bool NotStarted => !Started;
public bool StartedAndNotActivated => Started && !Activated;
public bool StartedAndActivated => Started && Activated;
public async Task InitAsync()
{
var started = await _storageService.GetAsync<bool?>(StartedKey);
var activated = await _storageService.GetAsync<bool?>(ActivatedKey);
Started = started.GetValueOrDefault();
Activated = activated.GetValueOrDefault();
}
public void ShowExtension()
{
_messagingService.Send("showAppExtension", this);
}
public void EnabledExtension(bool enabled)
{
Started = true;
if(!Activated && enabled)
{
Activated = enabled;
}
}
}
}

View File

@@ -46,7 +46,10 @@ namespace Bit.App.Pages
if(EditMode)
{
var folder = await _folderService.GetAsync(FolderId);
Folder = await folder.DecryptAsync();
if(folder != null)
{
Folder = await folder.DecryptAsync();
}
}
else
{
@@ -57,6 +60,10 @@ namespace Bit.App.Pages
public async Task<bool> SubmitAsync()
{
if(Folder == null)
{
return false;
}
if(Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.None)
{
await _platformUtilsService.ShowDialogAsync(AppResources.InternetConnectionRequiredMessage,
@@ -93,6 +100,10 @@ namespace Bit.App.Pages
public async Task<bool> DeleteAsync()
{
if(Folder == null)
{
return false;
}
if(Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.None)
{
await _platformUtilsService.ShowDialogAsync(AppResources.InternetConnectionRequiredMessage,

View File

@@ -16,13 +16,15 @@
<pages:FoldersPageViewModel />
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
</ContentPage.ToolbarItems>
<ContentPage.Resources>
<ResourceDictionary>
<u:InverseBoolConverter x:Key="inverseBool" />
<ToolbarItem x:Name="_closeItem" x:Key="closeItem" Text="{u:I18n Close}"
Clicked="Close_Clicked" Order="Primary" Priority="-1" />
<ToolbarItem x:Name="_addItem" x:Key="addItem" Icon="plus.png"
Clicked="AddButton_Clicked" Order="Primary"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n AddItem}" />
<StackLayout x:Name="_mainLayout" x:Key="mainLayout">
<Label IsVisible="{Binding ShowNoData}"
Text="{u:I18n NoFoldersToList}"
@@ -68,7 +70,9 @@
x:Name="_fab"
ImageName="plus.png"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize">
AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n AddFolder}">
</fab:FloatingActionButtonView>
</AbsoluteLayout>

View File

@@ -18,10 +18,11 @@ namespace Bit.App.Pages
if(Device.RuntimePlatform == Device.iOS)
{
_absLayout.Children.Remove(_fab);
ToolbarItems.Add(_closeItem);
ToolbarItems.Add(_addItem);
}
else
{
ToolbarItems.RemoveAt(0);
_fab.Clicked = AddButton_Clicked;
}
}

View File

@@ -19,7 +19,7 @@
<ScrollView Padding="0, 0, 0, 20">
<StackLayout Padding="0" Spacing="20">
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row, box-row-input">
<StackLayout StyleClass="box-row, box-row-input, box-row-input-options-platform">
<Label
Text="{u:I18n Theme}"
StyleClass="box-label" />
@@ -35,7 +35,7 @@
x:Name="_themeDescriptionLabel" />
</StackLayout>
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row, box-row-input">
<StackLayout StyleClass="box-row, box-row-input, box-row-input-options-platform">
<Label
Text="{u:I18n DefaultUriMatchDetection}"
StyleClass="box-label" />
@@ -50,7 +50,7 @@
StyleClass="box-footer-label" />
</StackLayout>
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row, box-row-input">
<StackLayout StyleClass="box-row, box-row-input, box-row-input-options-platform">
<Label
Text="{u:I18n ClearClipboard}"
StyleClass="box-label" />
@@ -96,7 +96,7 @@
</StackLayout>
<StackLayout StyleClass="box" IsVisible="{Binding ShowAndroidAutofillSettings}">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n AutofillService}"
<Label Text="{u:I18n AutofillService, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<StackLayout StyleClass="box-row, box-row-switch">
@@ -134,7 +134,7 @@
</StackLayout>
<StackLayout StyleClass="box" IsVisible="{Binding ShowAndroidAccessibilitySettings}">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n AutofillAccessibilityService}"
<Label Text="{u:I18n AutofillAccessibilityService, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<StackLayout StyleClass="box-row, box-row-switch">

View File

@@ -2,6 +2,8 @@
using Bit.App.Resources;
using Bit.Core.Utilities;
using Xamarin.Forms;
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
namespace Bit.App.Pages
{
@@ -27,6 +29,12 @@ namespace Bit.App.Pages
_themeDescriptionLabel.Text = string.Concat(_themeDescriptionLabel.Text, " ",
AppResources.RestartIsRequired);
}
else
{
_themePicker.On<iOS>().SetUpdateMode(UpdateMode.WhenFinished);
_uriMatchPicker.On<iOS>().SetUpdateMode(UpdateMode.WhenFinished);
_clearClipboardPicker.On<iOS>().SetUpdateMode(UpdateMode.WhenFinished);
}
}
protected async override void OnAppearing()

View File

@@ -46,6 +46,7 @@ namespace Bit.App.Pages
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
PageTitle = AppResources.Options;
var iosIos = Device.RuntimePlatform == Device.iOS;
ClearClipboardOptions = new List<KeyValuePair<int?, string>>
{
@@ -53,21 +54,21 @@ namespace Bit.App.Pages
new KeyValuePair<int?, string>(10, AppResources.TenSeconds),
new KeyValuePair<int?, string>(20, AppResources.TwentySeconds),
new KeyValuePair<int?, string>(30, AppResources.ThirtySeconds),
new KeyValuePair<int?, string>(60, AppResources.OneMinute),
new KeyValuePair<int?, string>(120, AppResources.TwoMinutes),
new KeyValuePair<int?, string>(300, AppResources.FiveMinutes),
new KeyValuePair<int?, string>(60, AppResources.OneMinute)
};
if(!iosIos)
{
ClearClipboardOptions.Add(new KeyValuePair<int?, string>(120, AppResources.TwoMinutes));
ClearClipboardOptions.Add(new KeyValuePair<int?, string>(300, AppResources.FiveMinutes));
}
ThemeOptions = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>(null, AppResources.Default),
new KeyValuePair<string, string>("light", AppResources.Light),
new KeyValuePair<string, string>("dark", AppResources.Dark),
new KeyValuePair<string, string>("black", AppResources.Black),
new KeyValuePair<string, string>("nord", "Nord"),
};
if(Device.RuntimePlatform == Device.Android)
{
ThemeOptions.Add(new KeyValuePair<string, string>("black", AppResources.Black));
}
ThemeOptions.Add(new KeyValuePair<string, string>("nord", "Nord"));
UriMatchOptions = new List<KeyValuePair<UriMatchType?, string>>
{
new KeyValuePair<UriMatchType?, string>(UriMatchType.Domain, AppResources.BaseDomain),
@@ -300,6 +301,11 @@ namespace Bit.App.Pages
await Task.Delay(1000);
}
_messagingService.Send("updatedTheme", theme);
if(Device.RuntimePlatform == Device.iOS)
{
await Task.Delay(500);
await _platformUtilsService.ShowDialogAsync(AppResources.ThemeAppliedOnRestart);
}
}
}

View File

@@ -47,7 +47,8 @@
<ListView
ItemsSource="{Binding GroupedItems}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
HasUnevenRows="True"
RowHeight="-1"
ItemTemplate="{StaticResource listItemDataTemplateSelector}"
IsGroupingEnabled="True"
ItemSelected="RowSelected"
@@ -56,14 +57,18 @@
<ListView.GroupHeaderTemplate>
<DataTemplate x:DataType="pages:SettingsPageListGroup">
<ViewCell>
<StackLayout Padding="0" Spacing="0">
<BoxView StyleClass="list-section-separator"
IsVisible="{Binding First, Converter={StaticResource inverseBool}}" />
<StackLayout StyleClass="list-row-header">
<StackLayout
Padding="0" Spacing="0" VerticalOptions="FillAndExpand"
StyleClass="list-row-header-container, list-row-header-container-platform">
<BoxView
StyleClass="list-section-separator-top, list-section-separator-top-platform"
IsVisible="{Binding First, Converter={StaticResource inverseBool}}" />
<StackLayout StyleClass="list-row-header, list-row-header-platform">
<Label
Text="{Binding Name}"
StyleClass="list-header, list-header-platform" />
</StackLayout>
<BoxView StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform" />
</StackLayout>
</ViewCell>
</DataTemplate>

View File

@@ -67,11 +67,11 @@ namespace Bit.App.Pages
}
else if(item.Name == AppResources.PasswordAutofill)
{
// await Navigation.PushModalAsync(new NavigationPage(new OptionsPage()));
await Navigation.PushModalAsync(new NavigationPage(new AutofillPage()));
}
else if(item.Name == AppResources.AppExtension)
{
// await Navigation.PushModalAsync(new NavigationPage(new OptionsPage()));
await Navigation.PushModalAsync(new NavigationPage(new ExtensionPage()));
}
else if(item.Name == AppResources.Options)
{

View File

@@ -23,7 +23,6 @@ namespace Bit.App.Pages
private readonly IStorageService _storageService;
private readonly ISyncService _syncService;
private string _fingerprintName;
private bool _supportsFingerprint;
private bool _pin;
private bool _fingerprint;
@@ -57,12 +56,6 @@ namespace Bit.App.Pages
GroupedItems = new ExtendedObservableCollection<SettingsPageListGroup>();
PageTitle = AppResources.Settings;
_fingerprintName = AppResources.Fingerprint;
if(Device.RuntimePlatform == Device.iOS)
{
_fingerprintName = _deviceActionService.SupportsFaceId() ? AppResources.FaceID : AppResources.TouchID;
}
}
public ExtendedObservableCollection<SettingsPageListGroup> GroupedItems { get; set; }
@@ -329,9 +322,15 @@ namespace Bit.App.Pages
};
if(_supportsFingerprint)
{
var fingerprintName = AppResources.Fingerprint;
if(Device.RuntimePlatform == Device.iOS)
{
fingerprintName = _deviceActionService.SupportsFaceId() ?
AppResources.FaceID : AppResources.TouchID;
}
var item = new SettingsPageListItem
{
Name = string.Format(AppResources.UnlockWith, _fingerprintName),
Name = string.Format(AppResources.UnlockWith, fingerprintName),
SubLabel = _fingerprint ? AppResources.Enabled : AppResources.Disabled
};
securityItems.Insert(1, item);

View File

@@ -15,17 +15,7 @@
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
<ToolbarItem Text="{u:I18n Save}" Clicked="Save_Clicked" Order="Primary" />
<ToolbarItem Text="{u:I18n Attachments}"
Clicked="Attachments_Clicked"
Order="Secondary"
x:Name="_attachmentsItem" />
<ToolbarItem Text="{u:I18n Delete}"
Clicked="Delete_Clicked"
Order="Secondary"
IsDestructive="True"
x:Name="_deleteItem" />
</ContentPage.ToolbarItems>
<ContentPage.Resources>
@@ -33,16 +23,33 @@
<u:InverseBoolConverter x:Key="inverseBool" />
<u:StringHasValueConverter x:Key="stringHasValue" />
<u:IsNotNullConverter x:Key="notNull" />
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
x:Key="closeItem" x:Name="_closeItem" />
<ToolbarItem Text="{u:I18n Collections}"
x:Key="collectionsItem"
x:Name="_collectionsItem"
Clicked="Collections_Clicked"
Order="Secondary" />
x:Key="collectionsItem"
x:Name="_collectionsItem"
Clicked="Collections_Clicked"
Order="Secondary" />
<ToolbarItem Text="{u:I18n Share}"
x:Key="shareItem"
x:Name="_shareItem"
Clicked="Share_Clicked"
Order="Secondary" />
x:Key="shareItem"
x:Name="_shareItem"
Clicked="Share_Clicked"
Order="Secondary" />
<ToolbarItem Icon="more_vert.png" Clicked="More_Clicked" Order="Primary" x:Name="_moreItem"
x:Key="moreItem"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n Options}" />
<ToolbarItem Text="{u:I18n Attachments}"
Clicked="Attachments_Clicked"
Order="Secondary"
x:Name="_attachmentsItem"
x:Key="attachmentsItem" />
<ToolbarItem Text="{u:I18n Delete}"
Clicked="Delete_Clicked"
Order="Secondary"
IsDestructive="True"
x:Name="_deleteItem"
x:Key="deleteItem" />
</ResourceDictionary>
</ContentPage.Resources>
@@ -50,7 +57,7 @@
<StackLayout Spacing="20">
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n ItemInformation}"
<Label Text="{u:I18n ItemInformation, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<StackLayout StyleClass="box-row, box-row-input"
@@ -105,7 +112,9 @@
StyleClass="box-value"
Grid.Row="1"
Grid.Column="0"
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}" />
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
IsSpellCheckEnabled="False"
IsTextPredictionEnabled="False" />
<controls:FaButton
StyleClass="box-row-button, box-row-button-platform"
Text="&#xf058;"
@@ -146,6 +155,8 @@
<controls:MonoEntry
x:Name="_loginTotpEntry"
Text="{Binding Cipher.Login.Totp}"
IsSpellCheckEnabled="False"
IsTextPredictionEnabled="False"
StyleClass="box-value"
Grid.Row="1"
Grid.Column="0" />
@@ -229,7 +240,9 @@
Grid.Row="1"
Grid.Column="0"
Keyboard="Numeric"
IsPassword="{Binding ShowCardCode, Converter={StaticResource inverseBool}}" />
IsPassword="{Binding ShowCardCode, Converter={StaticResource inverseBool}}"
IsSpellCheckEnabled="False"
IsTextPredictionEnabled="False" />
<controls:FaButton
StyleClass="box-row-button, box-row-button-platform"
Text="{Binding ShowCardCodeIcon}"
@@ -328,6 +341,7 @@
StyleClass="box-label" />
<Entry
x:Name="_identityEmailEntry"
Keyboard="Email"
Text="{Binding Cipher.Identity.Email}"
StyleClass="box-value" />
</StackLayout>
@@ -407,7 +421,7 @@
</StackLayout>
<StackLayout StyleClass="box" IsVisible="{Binding IsLogin}">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n URIs}"
<Label Text="{u:I18n URIs, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<controls:RepeaterView ItemsSource="{Binding Uris}">
@@ -450,7 +464,7 @@
</StackLayout>
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n Miscellaneous}"
<Label Text="{u:I18n Miscellaneous, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<StackLayout StyleClass="box-row, box-row-input">
@@ -477,7 +491,7 @@
</StackLayout>
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n Notes}"
<Label Text="{u:I18n Notes, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<StackLayout StyleClass="box-row, box-row-input">
@@ -487,10 +501,11 @@
Text="{Binding Cipher.Notes}"
StyleClass="box-value" />
</StackLayout>
<BoxView StyleClass="box-row-separator" IsVisible="{Binding ShowNotesSeparator}" />
</StackLayout>
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n CustomFields}"
<Label Text="{u:I18n CustomFields, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<controls:RepeaterView ItemsSource="{Binding Fields}">
@@ -534,7 +549,9 @@
Grid.Row="1"
Grid.Column="0"
IsVisible="{Binding IsHiddenType}"
IsPassword="{Binding ShowHiddenValue, Converter={StaticResource inverseBool}}" />
IsPassword="{Binding ShowHiddenValue, Converter={StaticResource inverseBool}}"
IsSpellCheckEnabled="False"
IsTextPredictionEnabled="False" />
<Switch
IsToggled="{Binding BooleanValue}"
Grid.Row="0"
@@ -568,7 +585,7 @@
</StackLayout>
<StackLayout StyleClass="box" IsVisible="{Binding EditMode, Converter={StaticResource inverseBool}}">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n Ownership}"
<Label Text="{u:I18n Ownership, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<StackLayout StyleClass="box-row, box-row-input">
@@ -584,7 +601,7 @@
</StackLayout>
<StackLayout StyleClass="box" IsVisible="{Binding ShowCollections}">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n Collections}"
<Label Text="{u:I18n Collections, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<StackLayout Spacing="0" Padding="0"

View File

@@ -8,6 +8,8 @@ using Bit.Core.Utilities;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
namespace Bit.App.Pages
{
@@ -46,14 +48,22 @@ namespace Bit.App.Pages
_vm.DefaultUri = uri ?? appOptions?.Uri;
_vm.Init();
SetActivityIndicator();
if(!_vm.EditMode || Device.RuntimePlatform == Device.iOS)
if(_vm.EditMode && Device.RuntimePlatform == Device.Android)
{
ToolbarItems.Remove(_attachmentsItem);
ToolbarItems.Remove(_deleteItem);
ToolbarItems.Add(_attachmentsItem);
ToolbarItems.Add(_deleteItem);
}
if(Device.RuntimePlatform == Device.Android)
if(Device.RuntimePlatform == Device.iOS)
{
ToolbarItems.RemoveAt(0);
ToolbarItems.Add(_closeItem);
if(_vm.EditMode)
{
ToolbarItems.Add(_moreItem);
}
_vm.ShowNotesSeparator = true;
_typePicker.On<iOS>().SetUpdateMode(UpdateMode.WhenFinished);
_ownershipPicker.On<iOS>().SetUpdateMode(UpdateMode.WhenFinished);
}
_typePicker.ItemDisplayBinding = new Binding("Key");
@@ -151,7 +161,7 @@ namespace Bit.App.Pages
{
if(FromAutofillFramework)
{
Application.Current.MainPage = new TabsPage();
Xamarin.Forms.Application.Current.MainPage = new TabsPage();
return true;
}
return base.OnBackButtonPressed();
@@ -161,7 +171,8 @@ namespace Bit.App.Pages
{
if(DoOnce())
{
await Navigation.PushModalAsync(new NavigationPage(new PasswordHistoryPage(_vm.CipherId)));
await Navigation.PushModalAsync(
new Xamarin.Forms.NavigationPage(new PasswordHistoryPage(_vm.CipherId)));
}
}
@@ -188,7 +199,7 @@ namespace Bit.App.Pages
if(DoOnce())
{
var page = new AttachmentsPage(_vm.CipherId);
await Navigation.PushModalAsync(new NavigationPage(page));
await Navigation.PushModalAsync(new Xamarin.Forms.NavigationPage(page));
}
}
@@ -197,7 +208,7 @@ namespace Bit.App.Pages
if(DoOnce())
{
var page = new SharePage(_vm.CipherId);
await Navigation.PushModalAsync(new NavigationPage(page));
await Navigation.PushModalAsync(new Xamarin.Forms.NavigationPage(page));
}
}
@@ -217,7 +228,7 @@ namespace Bit.App.Pages
if(DoOnce())
{
var page = new CollectionsPage(_vm.CipherId);
await Navigation.PushModalAsync(new NavigationPage(page));
await Navigation.PushModalAsync(new Xamarin.Forms.NavigationPage(page));
}
}
@@ -233,7 +244,44 @@ namespace Bit.App.Pages
await _vm.UpdateTotpKeyAsync(key);
});
});
await Navigation.PushModalAsync(new NavigationPage(page));
await Navigation.PushModalAsync(new Xamarin.Forms.NavigationPage(page));
}
}
private async void More_Clicked(object sender, System.EventArgs e)
{
if(!DoOnce())
{
return;
}
var options = new List<string> { AppResources.Attachments };
if(_vm.EditMode)
{
options.Add(_vm.Cipher.OrganizationId == null ? AppResources.Share : AppResources.Collections);
}
var selection = await DisplayActionSheet(AppResources.Options, AppResources.Cancel,
_vm.EditMode ? AppResources.Delete : null, options.ToArray());
if(selection == AppResources.Delete)
{
if(await _vm.DeleteAsync())
{
await Navigation.PopModalAsync();
}
}
else if(selection == AppResources.Attachments)
{
var page = new AttachmentsPage(_vm.CipherId);
await Navigation.PushModalAsync(new Xamarin.Forms.NavigationPage(page));
}
else if(selection == AppResources.Collections)
{
var page = new CollectionsPage(_vm.CipherId);
await Navigation.PushModalAsync(new Xamarin.Forms.NavigationPage(page));
}
else if(selection == AppResources.Share)
{
var page = new SharePage(_vm.CipherId);
await Navigation.PushModalAsync(new Xamarin.Forms.NavigationPage(page));
}
}

View File

@@ -24,6 +24,7 @@ namespace Bit.App.Pages
private readonly IAuditService _auditService;
private readonly IMessagingService _messagingService;
private CipherView _cipher;
private bool _showNotesSeparator;
private bool _showPassword;
private bool _showCardCode;
private int _typeSelectedIndex;
@@ -224,6 +225,11 @@ namespace Bit.App.Pages
get => _cipher;
set => SetProperty(ref _cipher, value, additionalPropertyNames: _additionalCipherProperties);
}
public bool ShowNotesSeparator
{
get => _showNotesSeparator;
set => SetProperty(ref _showNotesSeparator, value);
}
public bool ShowPassword
{
get => _showPassword;
@@ -367,6 +373,10 @@ namespace Bit.App.Pages
public async Task<bool> SubmitAsync()
{
if(Cipher == null)
{
return false;
}
if(Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.None)
{
await _platformUtilsService.ShowDialogAsync(AppResources.InternetConnectionRequiredMessage,
@@ -381,10 +391,10 @@ namespace Bit.App.Pages
return false;
}
Cipher.Fields = Fields.Any() ? Fields.Select(f => f.Field).ToList() : null;
Cipher.Fields = Fields != null && Fields.Any() ? Fields.Select(f => f.Field).ToList() : null;
if(Cipher.Login != null)
{
Cipher.Login.Uris = Uris.ToList();
Cipher.Login.Uris = Uris?.ToList();
if(!EditMode && Cipher.Type == CipherType.Login && (Cipher.Login.Uris?.Count ?? 0) == 1 &&
string.IsNullOrWhiteSpace(Cipher.Login.Uris.First().Uri))
{
@@ -406,6 +416,10 @@ namespace Bit.App.Pages
}
var cipher = await _cipherService.EncryptAsync(Cipher);
if(cipher == null)
{
return false;
}
try
{
await _deviceActionService.ShowLoadingAsync(AppResources.Saving);
@@ -414,7 +428,7 @@ namespace Bit.App.Pages
await _deviceActionService.HideLoadingAsync();
_platformUtilsService.ShowToast("success", null,
EditMode ? AppResources.ItemUpdated : AppResources.NewItemCreated);
_messagingService.Send(EditMode ? "editedCipher" : "addedCipher");
_messagingService.Send(EditMode ? "editedCipher" : "addedCipher", Cipher.Id);
if((Page as AddEditPage).FromAutofillFramework)
{
@@ -455,7 +469,7 @@ namespace Bit.App.Pages
await _cipherService.DeleteWithServerAsync(Cipher.Id);
await _deviceActionService.HideLoadingAsync();
_platformUtilsService.ShowToast("success", null, AppResources.ItemDeleted);
_messagingService.Send("deletedCipher");
_messagingService.Send("deletedCipher", Cipher);
return true;
}
catch(ApiException e)

View File

@@ -30,9 +30,9 @@
<ScrollView x:Name="_scrollView">
<StackLayout Spacing="20">
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row"
<StackLayout StyleClass="box-row" Padding="10, 20"
IsVisible="{Binding HasAttachments, Converter={StaticResource inverseBool}}">
<Label Text="{u:I18n NoAttachments}" />
<Label Text="{u:I18n NoAttachments}" HorizontalTextAlignment="Center" />
</StackLayout>
<controls:RepeaterView ItemsSource="{Binding Attachments}" IsVisible="{Binding HasAttachments}">
<controls:RepeaterView.ItemTemplate>
@@ -64,7 +64,7 @@
</StackLayout>
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n AddNewAttachment}"
<Label Text="{u:I18n AddNewAttachment, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<StackLayout StyleClass="box-row">

View File

@@ -45,7 +45,10 @@ namespace Bit.App.Pages
protected override void OnDisappearing()
{
base.OnDisappearing();
_broadcasterService.Unsubscribe(nameof(AttachmentsPage));
if(Device.RuntimePlatform != Device.iOS)
{
_broadcasterService.Unsubscribe(nameof(AttachmentsPage));
}
}
private async void Save_Clicked(object sender, EventArgs e)

View File

@@ -21,7 +21,7 @@
<ContentPage.Resources>
<ResourceDictionary>
<u:InverseBoolConverter x:Key="inverseBool" />
<DataTemplate x:Key="cipherTemplate"
x:DataType="pages:GroupingsPageListItem">
<controls:CipherViewCell
@@ -63,13 +63,19 @@
<ListView.GroupHeaderTemplate>
<DataTemplate x:DataType="pages:GroupingsPageListGroup">
<ViewCell>
<StackLayout StyleClass="list-row-header">
<Label
Text="{Binding Name}"
StyleClass="list-header, list-header-platform" />
<Label
Text="{Binding ItemCount}"
StyleClass="list-header-sub" />
<StackLayout
Spacing="0" Padding="0" VerticalOptions="FillAndExpand"
StyleClass="list-row-header-container, list-row-header-container-platform">
<BoxView
StyleClass="list-section-separator-top, list-section-separator-top-platform" />
<StackLayout StyleClass="list-row-header, list-row-header-platform">
<Label
Text="{Binding Name}"
StyleClass="list-header, list-header-platform" />
<Label
Text="{Binding ItemCount}"
StyleClass="list-header-sub" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>

View File

@@ -3,6 +3,8 @@ using Bit.App.Resources;
using Bit.Core.Abstractions;
using Bit.Core.Enums;
using Bit.Core.Utilities;
using System;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace Bit.App.Pages
@@ -31,7 +33,15 @@ namespace Bit.App.Pages
base.OnAppearing();
await LoadOnAppearedAsync(_mainLayout, false, async () =>
{
await _vm.LoadAsync();
try
{
await _vm.LoadAsync();
}
catch(Exception e) when(e.Message.Contains("No key."))
{
await Task.Delay(5000);
await _vm.LoadAsync();
}
}, _mainContent);
}

View File

@@ -112,6 +112,10 @@ namespace Bit.App.Pages
public async Task SelectCipherAsync(CipherView cipher, bool fuzzy)
{
if(cipher == null)
{
return;
}
if(_deviceActionService.SystemMajorVersion() < 21)
{
await AppHelpers.CipherListOptions(Page, cipher);

View File

@@ -15,39 +15,38 @@
<pages:CiphersPageViewModel />
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
</ContentPage.ToolbarItems>
<ContentPage.Resources>
<ResourceDictionary>
<u:DateTimeConverter x:Key="dateTime" />
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
x:Name="_closeItem" x:Key="closeItem" />
<StackLayout
Orientation="Horizontal"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
Spacing="0"
Padding="0"
x:Name="_titleLayout"
x:Key="titleLayout">
<controls:MiButton
StyleClass="btn-title, btn-title-platform"
Text="&#xe5c4;"
VerticalOptions="CenterAndExpand"
Clicked="BackButton_Clicked"
x:Name="_backButton" />
<SearchBar
x:Name="_searchBar"
HorizontalOptions="FillAndExpand"
TextChanged="SearchBar_TextChanged"
SearchButtonPressed="SearchBar_SearchButtonPressed"
Placeholder="{Binding PageTitle}" />
</StackLayout>
<BoxView StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform"
x:Name="_separator" x:Key="separator" />
</ResourceDictionary>
</ContentPage.Resources>
<NavigationPage.TitleView>
<StackLayout
Orientation="Horizontal"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
Spacing="0"
Padding="0">
<controls:MiButton
StyleClass="btn-title, btn-title-platform"
Text="&#xe5c4;"
VerticalOptions="CenterAndExpand"
Clicked="BackButton_Clicked" />
<SearchBar
x:Name="_searchBar"
HorizontalOptions="FillAndExpand"
BackgroundColor="Transparent"
TextChanged="SearchBar_TextChanged"
SearchButtonPressed="SearchBar_SearchButtonPressed"
Placeholder="{Binding PageTitle}" />
</StackLayout>
</NavigationPage.TitleView>
<StackLayout x:Name="_mainLayout">
<StackLayout x:Name="_mainLayout" Spacing="0" Padding="0">
<controls:FaLabel IsVisible="{Binding ShowSearchDirection}"
Text="&#xf002;"
StyleClass="text-muted"
@@ -62,13 +61,13 @@
HorizontalOptions="CenterAndExpand"
HorizontalTextAlignment="Center" />
<ListView x:Name="_listView"
IsVisible="{Binding ShowList}"
ItemsSource="{Binding Ciphers}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
CachingStrategy="RecycleElement"
ItemSelected="RowSelected"
StyleClass="list, list-platform">
IsVisible="{Binding ShowList}"
ItemsSource="{Binding Ciphers}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
CachingStrategy="RecycleElement"
ItemSelected="RowSelected"
StyleClass="list, list-platform">
<ListView.ItemTemplate>
<DataTemplate x:DataType="views:CipherView">
<controls:CipherViewCell

View File

@@ -40,9 +40,16 @@ namespace Bit.App.Pages
_vm.PageTitle = AppResources.SearchVault;
}
if(Device.RuntimePlatform == Device.Android)
if(Device.RuntimePlatform == Device.iOS)
{
ToolbarItems.RemoveAt(0);
ToolbarItems.Add(_closeItem);
_searchBar.Placeholder = AppResources.Search;
_mainLayout.Children.Insert(0, _searchBar);
_mainLayout.Children.Insert(1, _separator);
}
else
{
NavigationPage.SetTitleView(this, _titleLayout);
}
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
}
@@ -121,12 +128,9 @@ namespace Bit.App.Pages
}
}
private async void Close_Clicked(object sender, System.EventArgs e)
private void Close_Clicked(object sender, EventArgs e)
{
if(DoOnce())
{
await Navigation.PopModalAsync();
}
GoBack();
}
}
}

View File

@@ -75,6 +75,10 @@ namespace Bit.App.Pages
{
WebsiteIconsEnabled = !(await _stateService.GetAsync<bool?>(Constants.DisableFaviconKey))
.GetValueOrDefault();
if(!string.IsNullOrWhiteSpace((Page as CiphersPage).SearchBar.Text))
{
Search((Page as CiphersPage).SearchBar.Text, 500);
}
}
public void Search(string searchText, int? timeout = null)
@@ -126,7 +130,7 @@ namespace Bit.App.Pages
if(!string.IsNullOrWhiteSpace(AutofillUrl))
{
var options = new List<string> { AppResources.Autofill };
if(cipher.Type == CipherType.Login &&
if(cipher.Type == CipherType.Login &&
Xamarin.Essentials.Connectivity.NetworkAccess != Xamarin.Essentials.NetworkAccess.None)
{
options.Add(AppResources.AutofillAndSave);

View File

@@ -28,9 +28,9 @@
<ScrollView x:Name="_scrollView">
<StackLayout Spacing="20">
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row"
<StackLayout StyleClass="box-row" Padding="10, 20"
IsVisible="{Binding HasCollections, Converter={StaticResource inverseBool}}">
<Label Text="{u:I18n NoCollectionsToList}" />
<Label Text="{u:I18n NoCollectionsToList}" HorizontalTextAlignment="Center" />
</StackLayout>
<controls:RepeaterView ItemsSource="{Binding Collections}" IsVisible="{Binding HasCollections}">
<controls:RepeaterView.ItemTemplate>

View File

@@ -58,7 +58,8 @@ namespace Bit.App.Pages
public async Task<bool> SubmitAsync()
{
if(!Collections.Any(c => c.Checked))
var selectedCollectionIds = Collections?.Where(c => c.Checked).Select(c => c.Collection.Id);
if(!selectedCollectionIds?.Any() ?? true)
{
await Page.DisplayAlert(AppResources.AnErrorHasOccurred, AppResources.SelectOneCollection,
AppResources.Ok);
@@ -71,8 +72,7 @@ namespace Bit.App.Pages
return false;
}
_cipherDomain.CollectionIds = new HashSet<string>(
Collections.Where(c => c.Checked).Select(c => c.Collection.Id));
_cipherDomain.CollectionIds = new HashSet<string>(selectedCollectionIds);
try
{
await _deviceActionService.ShowLoadingAsync(AppResources.Saving);

View File

@@ -16,7 +16,9 @@
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Icon="search.png" Clicked="Search_Clicked" />
<ToolbarItem Icon="search.png" Clicked="Search_Clicked"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n Search}" />
</ContentPage.ToolbarItems>
<ContentPage.Resources>
@@ -29,6 +31,10 @@
Clicked="Lock_Clicked" Order="Secondary" />
<ToolbarItem x:Name="_exitItem" x:Key="exitItem" Text="{u:I18n Exit}"
Clicked="Exit_Clicked" Order="Secondary" />
<ToolbarItem x:Name="_addItem" x:Key="addItem" Icon="plus.png"
Clicked="AddButton_Clicked" Order="Primary"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n AddItem}" />
<DataTemplate x:Key="cipherTemplate"
x:DataType="pages:GroupingsPageListItem">
@@ -89,9 +95,10 @@
IsVisible="{Binding ShowList}"
ItemsSource="{Binding GroupedItems}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
HasUnevenRows="True"
RowHeight="-1"
RefreshCommand="{Binding RefreshCommand}"
IsPullToRefreshEnabled="true"
IsPullToRefreshEnabled="True"
IsRefreshing="{Binding Refreshing}"
ItemTemplate="{StaticResource listItemDataTemplateSelector}"
IsGroupingEnabled="True"
@@ -104,10 +111,13 @@
<ListView.GroupHeaderTemplate>
<DataTemplate x:DataType="pages:GroupingsPageListGroup">
<ViewCell>
<StackLayout Spacing="0" Padding="0">
<BoxView StyleClass="list-section-separator"
IsVisible="{Binding First, Converter={StaticResource inverseBool}}" />
<StackLayout StyleClass="list-row-header">
<StackLayout
Spacing="0" Padding="0" VerticalOptions="FillAndExpand"
StyleClass="list-row-header-container, list-row-header-container-platform">
<BoxView
StyleClass="list-section-separator-top, list-section-separator-top-platform"
IsVisible="{Binding First, Converter={StaticResource inverseBool}}" />
<StackLayout StyleClass="list-row-header, list-row-header-platform">
<Label
Text="{Binding Name}"
StyleClass="list-header, list-header-platform" />
@@ -115,6 +125,7 @@
Text="{Binding ItemCount}"
StyleClass="list-header-sub" />
</StackLayout>
<BoxView StyleClass="list-section-separator-bottom, list-section-separator-bottom-platform" />
</StackLayout>
</ViewCell>
</DataTemplate>
@@ -137,7 +148,9 @@
x:Name="_fab"
ImageName="plus.png"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize">
AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n AddItem}">
</fab:FloatingActionButtonView>
</AbsoluteLayout>

View File

@@ -49,6 +49,7 @@ namespace Bit.App.Pages
if(Device.RuntimePlatform == Device.iOS)
{
_absLayout.Children.Remove(_fab);
ToolbarItems.Add(_addItem);
}
else
{
@@ -77,15 +78,14 @@ namespace Bit.App.Pages
}
else if(message.Command == "syncCompleted")
{
if(!_vm.LoadedOnce)
{
return;
}
await Task.Delay(500);
Device.BeginInvokeOnMainThread(() =>
{
IsBusy = false;
var task = _vm.LoadAsync();
if(_vm.LoadedOnce)
{
var task = _vm.LoadAsync();
}
});
}
});
@@ -115,7 +115,7 @@ namespace Bit.App.Pages
}
// Forced sync if for some reason we have no data after a v1 migration
if(_vm.MainPage && !_syncService.SyncInProgress && migratedFromV1.GetValueOrDefault() &&
!_vm.HasCiphers && !_vm.HasFolders &&
!_vm.HasCiphers &&
Xamarin.Essentials.Connectivity.NetworkAccess != Xamarin.Essentials.NetworkAccess.None)
{
var triedV1ReSync = await _storageService.GetAsync<bool?>(Constants.TriedV1Resync);

View File

@@ -328,7 +328,7 @@ namespace Bit.App.Pages
{
Folders = await _folderService.GetAllDecryptedAsync();
NestedFolders = await _folderService.GetAllNestedAsync();
HasFolders = NestedFolders.Any();
HasFolders = NestedFolders.Any(f => f.Node?.Id != null);
Collections = await _collectionService.GetAllDecryptedAsync();
NestedCollections = await _collectionService.GetAllNestedAsync(Collections);
HasCollections = NestedCollections.Any();
@@ -366,6 +366,7 @@ namespace Bit.App.Pages
if(collectionNode?.Node != null)
{
PageTitle = collectionNode.Node.Name;
NestedCollections = (collectionNode.Children?.Count ?? 0) > 0 ? collectionNode.Children : null;
}
Filter = c => c.CollectionIds?.Contains(CollectionId) ?? false;
}

View File

@@ -27,12 +27,15 @@
<ScrollView x:Name="_scrollView">
<StackLayout Spacing="20">
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row"
IsVisible="{Binding HasOrganizations, Converter={StaticResource inverseBool}}">
<Label Text="{u:I18n NoOrgsToList}" />
<StackLayout StyleClass="box"
IsVisible="{Binding HasOrganizations, Converter={StaticResource inverseBool}}">
<StackLayout StyleClass="box-row" Padding="10, 20">
<Label Text="{u:I18n NoOrgsToList}" HorizontalTextAlignment="Center" />
</StackLayout>
<StackLayout StyleClass="box-row, box-row-input">
</StackLayout>
<StackLayout StyleClass="box"
IsVisible="{Binding HasOrganizations}">
<StackLayout StyleClass="box-row, box-row-input, box-row-input-options-platform">
<Label
Text="{u:I18n Organization}"
StyleClass="box-label" />
@@ -49,7 +52,7 @@
<StackLayout StyleClass="box"
IsVisible="{Binding OrganizationId, Converter={StaticResource notNull}}">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n Collections}"
<Label Text="{u:I18n Collections, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<StackLayout StyleClass="box-row"

View File

@@ -1,4 +1,6 @@
using Xamarin.Forms;
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
namespace Bit.App.Pages
{
@@ -17,6 +19,10 @@ namespace Bit.App.Pages
{
ToolbarItems.RemoveAt(0);
}
else
{
_organizationPicker.On<iOS>().SetUpdateMode(UpdateMode.WhenFinished);
}
_organizationPicker.ItemDisplayBinding = new Binding("Key");
}

View File

@@ -86,7 +86,8 @@ namespace Bit.App.Pages
public async Task<bool> SubmitAsync()
{
if(!Collections?.Any(c => c.Checked) ?? true)
var selectedCollectionIds = Collections?.Where(c => c.Checked).Select(c => c.Collection.Id);
if(!selectedCollectionIds?.Any() ?? true)
{
await Page.DisplayAlert(AppResources.AnErrorHasOccurred, AppResources.SelectOneCollection,
AppResources.Ok);
@@ -102,8 +103,7 @@ namespace Bit.App.Pages
var cipherDomain = await _cipherService.GetAsync(CipherId);
var cipherView = await cipherDomain.DecryptAsync();
var checkedCollectionIds = new HashSet<string>(
Collections.Where(c => c.Checked).Select(c => c.Collection.Id));
var checkedCollectionIds = new HashSet<string>(selectedCollectionIds);
try
{
await _deviceActionService.ShowLoadingAsync(AppResources.Saving);

View File

@@ -16,13 +16,6 @@
<pages:ViewPageViewModel />
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
<ToolbarItem Text="{u:I18n Edit}" Clicked="EditToolbarItem_Clicked" Order="Primary" />
<ToolbarItem Text="{u:I18n Attachments}" Clicked="Attachments_Clicked" Order="Secondary" />
<ToolbarItem Text="{u:I18n Delete}" Clicked="Delete_Clicked" Order="Secondary" IsDestructive="True" />
</ContentPage.ToolbarItems>
<ContentPage.Resources>
<ResourceDictionary>
<u:InverseBoolConverter x:Key="inverseBool" />
@@ -38,12 +31,24 @@
x:Name="_shareItem"
Clicked="Share_Clicked"
Order="Secondary" />
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
x:Name="_closeItem" x:Key="closeItem" />
<ToolbarItem Text="{u:I18n Edit}" Clicked="EditToolbarItem_Clicked" Order="Primary"
x:Name="_editItem" x:Key="editItem" />
<ToolbarItem Icon="more_vert.png" Clicked="More_Clicked" Order="Primary"
x:Name="_moreItem" x:Key="moreItem"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n Options}" />
<ToolbarItem Text="{u:I18n Attachments}" Clicked="Attachments_Clicked" Order="Secondary"
x:Name="_attachmentsItem" x:Key="attachmentsItem" />
<ToolbarItem Text="{u:I18n Delete}" Clicked="Delete_Clicked" Order="Secondary" IsDestructive="True"
x:Name="_deleteItem" x:Key="deleteItem" />
<ScrollView x:Key="scrollView" x:Name="_scrollView">
<StackLayout Spacing="20" x:Name="_mainLayout">
<StackLayout StyleClass="box">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n ItemInformation}"
<Label Text="{u:I18n ItemInformation, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<StackLayout StyleClass="box-row">
@@ -115,6 +120,7 @@
StyleClass="box-value"
Grid.Row="1"
Grid.Column="0"
LineBreakMode="CharacterWrap"
IsVisible="{Binding ShowPassword}" />
<controls:FaButton
StyleClass="box-row-button, box-row-button-platform"
@@ -413,7 +419,7 @@
</StackLayout>
<StackLayout StyleClass="box" IsVisible="{Binding ShowUris}">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n URIs}"
<Label Text="{u:I18n URIs, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<controls:RepeaterView ItemsSource="{Binding Cipher.Login.Uris}">
@@ -474,7 +480,7 @@
<StackLayout StyleClass="box"
IsVisible="{Binding Cipher.Notes, Converter={StaticResource stringHasValue}}">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n Notes}"
<Label Text="{u:I18n Notes, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<StackLayout StyleClass="box-row">
@@ -491,7 +497,7 @@
</StackLayout>
<StackLayout StyleClass="box" IsVisible="{Binding Cipher.HasFields}">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n CustomFields}"
<Label Text="{u:I18n CustomFields, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<controls:RepeaterView ItemsSource="{Binding Fields}">
@@ -564,7 +570,7 @@
</StackLayout>
<StackLayout StyleClass="box" IsVisible="{Binding ShowAttachments}">
<StackLayout StyleClass="box-row-header">
<Label Text="{u:I18n Attachments}"
<Label Text="{u:I18n Attachments, Header=True}"
StyleClass="box-header, box-header-platform" />
</StackLayout>
<controls:RepeaterView ItemsSource="{Binding Cipher.Attachments}">
@@ -632,7 +638,9 @@
x:Name="_fab"
ImageName="pencil.png"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize">
AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n EditItem}">
</fab:FloatingActionButtonView>
</AbsoluteLayout>

View File

@@ -1,4 +1,5 @@
using Bit.Core.Abstractions;
using Bit.App.Resources;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using System.Collections.Generic;
using System.Threading.Tasks;
@@ -25,15 +26,16 @@ namespace Bit.App.Pages
if(Device.RuntimePlatform == Device.iOS)
{
_absLayout.Children.Remove(_fab);
ToolbarItems.RemoveAt(2);
ToolbarItems.RemoveAt(2);
ToolbarItems.Add(_closeItem);
ToolbarItems.Add(_editItem);
ToolbarItems.Add(_moreItem);
}
else
{
ToolbarItems.RemoveAt(0);
ToolbarItems.RemoveAt(0);
_fab.Clicked = EditButton_Clicked;
_mainLayout.Padding = new Thickness(0, 0, 0, 75);
ToolbarItems.Add(_attachmentsItem);
ToolbarItems.Add(_deleteItem);
}
}
@@ -145,6 +147,40 @@ namespace Bit.App.Pages
}
}
private async void More_Clicked(object sender, System.EventArgs e)
{
if(!DoOnce())
{
return;
}
var options = new List<string> { AppResources.Attachments };
options.Add(_vm.Cipher.OrganizationId == null ? AppResources.Share : AppResources.Collections);
var selection = await DisplayActionSheet(AppResources.Options, AppResources.Cancel,
AppResources.Delete, options.ToArray());
if(selection == AppResources.Delete)
{
if(await _vm.DeleteAsync())
{
await Navigation.PopModalAsync();
}
}
else if(selection == AppResources.Attachments)
{
var page = new AttachmentsPage(_vm.CipherId);
await Navigation.PushModalAsync(new NavigationPage(page));
}
else if(selection == AppResources.Collections)
{
var page = new CollectionsPage(_vm.CipherId);
await Navigation.PushModalAsync(new NavigationPage(page));
}
else if(selection == AppResources.Share)
{
var page = new SharePage(_vm.CipherId);
await Navigation.PushModalAsync(new NavigationPage(page));
}
}
private async void Close_Clicked(object sender, System.EventArgs e)
{
if(DoOnce())

View File

@@ -275,7 +275,7 @@ namespace Bit.App.Pages
await _cipherService.DeleteWithServerAsync(Cipher.Id);
await _deviceActionService.HideLoadingAsync();
_platformUtilsService.ShowToast("success", null, AppResources.ItemDeleted);
_messagingService.Send("deletedCipher");
_messagingService.Send("deletedCipher", Cipher);
return true;
}
catch(ApiException e)

View File

@@ -19,7 +19,7 @@ namespace Bit.App.Resources {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class AppResources {
@@ -807,6 +807,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Capitalize.
/// </summary>
public static string Capitalize {
get {
return ResourceManager.GetString("Capitalize", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cardholder Name.
/// </summary>
@@ -1932,6 +1941,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Include Number.
/// </summary>
public static string IncludeNumber {
get {
return ResourceManager.GetString("IncludeNumber", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please connect to the internet before continuing..
/// </summary>
@@ -3498,6 +3516,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Your theme changes will apply when the app is restarted..
/// </summary>
public static string ThemeAppliedOnRestart {
get {
return ResourceManager.GetString("ThemeAppliedOnRestart", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Change the application&apos;s color theme..
/// </summary>
@@ -3553,7 +3580,7 @@ namespace Bit.App.Resources {
}
/// <summary>
/// Looks up a localized string similar to Try Again.
/// Looks up a localized string similar to Try again.
/// </summary>
public static string TryAgain {
get {

View File

@@ -1556,4 +1556,14 @@
<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>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Your theme changes will apply when the app is restarted.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Capitalize</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Include Number</value>
</data>
</root>

View File

@@ -1556,4 +1556,14 @@
<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>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Your theme changes will apply when the app is restarted.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Capitalize</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Include Number</value>
</data>
</root>

View File

@@ -412,7 +412,7 @@
<value>Extensió de l'aplicació Bitwarden</value>
</data>
<data name="BitwardenAppExtensionAlert2" xml:space="preserve">
<value>The easiest way to add new logins to your vault is from the Bitwarden App Extension. Learn more about using the Bitwarden App Extension by navigating to the "Settings" screen.</value>
<value>La forma més senzilla d'afegir nous inicis de sessió a la vostra caixa forta és amb l'extensió d'aplicació Bitwarden. Obteniu més informació sobre el seu ús en la pantalla "Eines".</value>
</data>
<data name="BitwardenAppExtensionDescription" xml:space="preserve">
<value>Utilitzeu Bitwarden en Safari i altres aplicacions per omplir automàticament els vostres inicis de sessió.</value>
@@ -753,7 +753,7 @@
<value>Estat</value>
</data>
<data name="BitwardenAutofillServiceAlert2" xml:space="preserve">
<value>The easiest way to add new logins to your vault is from the Bitwarden Auto-fill Service. Learn more about using the Bitwarden Auto-fill Service by navigating to the "Settings" screen.</value>
<value>La forma més senzilla d'afegir nous inicis de sessió a la vostra caixa forta és amb el servei d'emplenament automàtic de Bitwarden. Obteniu més informació sobre com utilitzar el servei en la pantalla "Eines".</value>
</data>
<data name="Autofill" xml:space="preserve">
<value>Emplenament automàtic</value>
@@ -1302,7 +1302,7 @@
<value>Emplenament automàtic de contrasenya</value>
</data>
<data name="BitwardenAutofillAlert2" xml:space="preserve">
<value>The easiest way to add new logins to your vault is by using the Bitwarden Password AutoFill extension. Learn more about using the Bitwarden Password AutoFill extension by navigating to the "Settings" screen.</value>
<value>La forma més senzilla d'afegir nous inicis de sessió a la vostra caixa forta és mitjançant l'extensió Emplenament automàtic de contrasenya de Bitwarden. Obteniu més informació sobre l'ús de l'extensió de Bitwarden a la pantalla "Eines".</value>
</data>
<data name="InvalidEmail" xml:space="preserve">
<value>Ladreça electrònica no és vàlida.</value>
@@ -1323,21 +1323,21 @@
<value>Tots els elements</value>
</data>
<data name="URIs" xml:space="preserve">
<value>URIs</value>
<value>URI</value>
<comment>Plural form of a URI</comment>
</data>
<data name="CheckingPassword" xml:space="preserve">
<value>Comprovant la contrasenya...</value>
<value>S'està comprovant la contrasenya...</value>
<comment>A loading message when doing an exposed password check.</comment>
</data>
<data name="CheckPassword" xml:space="preserve">
<value>Comprova si la contrasenya ha estat exposada.</value>
</data>
<data name="PasswordExposed" xml:space="preserve">
<value>This password has been exposed {0} time(s) in data breaches. You should change it.</value>
<value>Aquesta contrasenya ha estat exposada {0} vegades en filtracions de seguretat de dades. Heu de canviar-la.</value>
</data>
<data name="PasswordSafe" xml:space="preserve">
<value>This password was not found in any known data breaches. It should be safe to use.</value>
<value>Aquesta contrasenya no s'ha trobat en cap filtració de dades coneguda. Hauries de poder utilitzar-la de manera segura.</value>
</data>
<data name="IdentityName" xml:space="preserve">
<value>Nom d'identitat</value>
@@ -1349,13 +1349,13 @@
<value>Historial de les contrasenyes</value>
</data>
<data name="Types" xml:space="preserve">
<value>Tipologies</value>
<value>Tipus</value>
</data>
<data name="NoPasswordsToList" xml:space="preserve">
<value>Sense contrasenyes per mostrar.</value>
<value>No hi ha cap contrasenya per llistar.</value>
</data>
<data name="NoItemsToList" xml:space="preserve">
<value>Sense elements per mostrar.</value>
<value>No hi ha cap element per llistar.</value>
</data>
<data name="SearchCollection" xml:space="preserve">
<value>Cerca a la col·lecció</value>
@@ -1364,19 +1364,19 @@
<value>Cerca a la carpeta</value>
</data>
<data name="SearchType" xml:space="preserve">
<value>Tipologia de cerca</value>
<value>Tipus de cerca</value>
</data>
<data name="Type" xml:space="preserve">
<value>Tipologia</value>
<value>Tipus</value>
</data>
<data name="MoveDown" xml:space="preserve">
<value>Mou avall</value>
<value>Desplaça cap avall</value>
</data>
<data name="MoveUp" xml:space="preserve">
<value>Mou amunt</value>
<value>Desplaça cap amunt</value>
</data>
<data name="Miscellaneous" xml:space="preserve">
<value>Miscel·lània</value>
<value>Diversos</value>
</data>
<data name="Ownership" xml:space="preserve">
<value>Propietat</value>
@@ -1385,10 +1385,10 @@
<value>Qui és el propietari d'aquest element?</value>
</data>
<data name="NoCollectionsToList" xml:space="preserve">
<value>Sense col·leccions per mostrar.</value>
<value>No hi ha cap col·lecció per llistar.</value>
</data>
<data name="ItemShared" xml:space="preserve">
<value>S'ha compartit l'element.</value>
<value>L'element s'ha compartit.</value>
</data>
<data name="SelectOneCollection" xml:space="preserve">
<value>Heu d'escollir com a mínim una col·lecció.</value>
@@ -1400,13 +1400,13 @@
<value>Comparteix l'element</value>
</data>
<data name="NoOrgsToList" xml:space="preserve">
<value>Sense organitzacions per mostrar.</value>
<value>No hi ha cap organització per llistar.</value>
</data>
<data name="ShareDesc" xml:space="preserve">
<value>Choose an organization that you wish to share this item with. Sharing transfers ownership of the item to the organization. You will no longer be the direct owner of this item once it has been shared.</value>
<value>Trieu una organització amb la qual vulgueu compartir aquest element. En compartir transferiu la propietat de l'element a l'organització. Ja no sereu el propietari directe d'aquest element una vegada que s'haja compartit.</value>
</data>
<data name="NumberOfWords" xml:space="preserve">
<value>Nombre de mots</value>
<value>Nombre de paraules</value>
</data>
<data name="Passphrase" xml:space="preserve">
<value>Frase de pas</value>
@@ -1415,7 +1415,7 @@
<value>Separador de paraules</value>
</data>
<data name="Clear" xml:space="preserve">
<value>Neteja</value>
<value>Esborra</value>
<comment>To clear something out. example: To clear browser history.</comment>
</data>
<data name="Generator" xml:space="preserve">
@@ -1423,18 +1423,18 @@
<comment>Short for "Password Generator"</comment>
</data>
<data name="NoFoldersToList" xml:space="preserve">
<value>Sense carpetes per mostrar.</value>
<value>No hi ha carpetes per llistar.</value>
</data>
<data name="FingerprintPhrase" xml:space="preserve">
<value>Frase d'empremta digital</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>
</data>
<data name="YourAccountsFingerprint" xml:space="preserve">
<value>Your account's fingerprint phrase</value>
<value>Frase d'empremta digital del vostre compte</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>
</data>
<data name="ShareVaultConfirmation" xml:space="preserve">
<value>Bitwarden allows you to share your vault with others by using an organization account. Would you like to visit the bitwarden.com website to learn more?</value>
<value>Bitwarden us permet compartir la vostra caixa forta amb altres usuaris mitjançant un compte d'organització. Voleu visitar el lloc web de bitwarden.com per obtenir més informació?</value>
</data>
<data name="ExportVault" xml:space="preserve">
<value>Exporta caixa forta</value>
@@ -1458,14 +1458,14 @@
<value>Estableix el teu codi PIN per desbloquejar Bitwarden. La configuració PIN es restablirà si tanqueu sessió de manera completa de l'aplicació.</value>
</data>
<data name="LoggedInAsOn" xml:space="preserve">
<value>Logged in as {0} on {1}.</value>
<value>Heu iniciat la sessió com a {0} en {1}.</value>
<comment>ex: Logged in as user@example.com on bitwarden.com.</comment>
</data>
<data name="VaultLockedMasterPassword" xml:space="preserve">
<value>Your vault is locked. Verify your master password to continue.</value>
<value>La caixa forta està bloquejada. Verifiqueu la contrasenya mestra per continuar.</value>
</data>
<data name="VaultLockedPIN" xml:space="preserve">
<value>Your vault is locked. Verify your PIN code to continue.</value>
<value>La caixa forta està bloquejada. Verifiqueu El codi PIN per continuar.</value>
</data>
<data name="Dark" xml:space="preserve">
<value>Fosc</value>
@@ -1498,15 +1498,15 @@
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
</data>
<data name="ClearClipboardDescription" xml:space="preserve">
<value>Automatically clear copied values from your clipboard.</value>
<value>Esborra automàticament els valors copiats del porta-retalls.</value>
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
</data>
<data name="DefaultUriMatchDetection" xml:space="preserve">
<value>Default URI Match Detection</value>
<value>Detecció de coincidències URI per defecte</value>
<comment>Default URI match detection for auto-fill.</comment>
</data>
<data name="DefaultUriMatchDetectionDescription" xml:space="preserve">
<value>Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill.</value>
<value>Trieu la manera predeterminada en que es gestiona la detecció de coincidència d'URI per als inicis de sessió en realitzar accions com l'emplenament automàtic.</value>
</data>
<data name="Theme" xml:space="preserve">
<value>Tema</value>
@@ -1520,40 +1520,50 @@
<comment>Referring to restarting the application.</comment>
</data>
<data name="Restarting" xml:space="preserve">
<value>Reiniciant...</value>
<value>S'està reiniciant...</value>
</data>
<data name="CopyNotes" xml:space="preserve">
<value>Copia notes</value>
</data>
<data name="Exit" xml:space="preserve">
<value>Surt</value>
<value>Tanca</value>
</data>
<data name="ExitConfirmation" xml:space="preserve">
<value>Are you sure you want to exit Bitwarden?</value>
<value>Esteu segur que voleu tancar Bitwarden?</value>
</data>
<data name="PINRequireMasterPasswordRestart" xml:space="preserve">
<value>You you want to require unlocking with your master password when the application is restarted?</value>
<value>Voleu sol·licitar el desbloqueig amb la vostra contrasenya mestra quan es reinicie laplicació?</value>
</data>
<data name="Black" xml:space="preserve">
<value>Negre</value>
<comment>The color black</comment>
</data>
<data name="BlacklistedUris" xml:space="preserve">
<value>URls de la llista negra</value>
<value>URl a la llista negra</value>
</data>
<data name="BlacklistedUrisDescription" xml:space="preserve">
<value>URIs that are blacklisted will not offer auto-fill. The list of apps should be comma separated. Ex: "https://twitter.com, androidapp://com.twitter.android".</value>
<value>Els URI que es mostren a la llista negra no oferiran lemplenament automàtic. La llista ha de estar separada per comes. Ex: "https://twitter.com, androidapp: //com.twitter.android".</value>
</data>
<data name="DisableSavePrompt" xml:space="preserve">
<value>Disable Save Prompt</value>
<value>Desactiva Guarda elements nous</value>
</data>
<data name="DisableSavePromptDescription" xml:space="preserve">
<value>The "Save Prompt" automatically prompts you to save new items to your vault whenever you enter them for the first time.</value>
<value>"Guarda elements nous" demanarà automàticament que guardeu elements nous al magatzem cada volta que els introduïu per primera vegada.</value>
</data>
<data name="LockOptionOnRestart" xml:space="preserve">
<value>On App Restart</value>
<value>En reiniciar aplicació</value>
</data>
<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>L'emplenament automàtic facilita l'accés de forma segura a la vostra caixa forta de Bitwarden des d'altres llocs web i aplicacions. Sembla que no heu habilitat un servei demplenament automàtic per a Bitwarden. Habiliteu-lo a la pantalla "Configuració".</value>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Els canvis de tema s'aplicaran quan es reinicie laplicació.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Majúscules inicials</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Inclou número</value>
</data>
</root>

View File

@@ -1305,255 +1305,265 @@
<value>The easiest way to add new logins to your vault is by using the Bitwarden Password AutoFill extension. Learn more about using the Bitwarden Password AutoFill extension by navigating to the "Settings" screen.</value>
</data>
<data name="InvalidEmail" xml:space="preserve">
<value>Invalid email address.</value>
<value>Neplatná e-mailová adresa.</value>
</data>
<data name="Cards" xml:space="preserve">
<value>Cards</value>
<value>Karty</value>
</data>
<data name="Identities" xml:space="preserve">
<value>Identities</value>
<value>Identity</value>
</data>
<data name="Logins" xml:space="preserve">
<value>Logins</value>
<value>Přihlašovací údaje</value>
</data>
<data name="SecureNotes" xml:space="preserve">
<value>Secure Notes</value>
<value>Poznámky</value>
</data>
<data name="AllItems" xml:space="preserve">
<value>All Items</value>
<value>Všechny položky</value>
</data>
<data name="URIs" xml:space="preserve">
<value>URIs</value>
<value>URI</value>
<comment>Plural form of a URI</comment>
</data>
<data name="CheckingPassword" xml:space="preserve">
<value>Checking password...</value>
<value>Prověřování hesla…</value>
<comment>A loading message when doing an exposed password check.</comment>
</data>
<data name="CheckPassword" xml:space="preserve">
<value>Check if password has been exposed.</value>
<value>Zkontrolujte, zda nedošlo k úniku hesla.</value>
</data>
<data name="PasswordExposed" xml:space="preserve">
<value>This password has been exposed {0} time(s) in data breaches. You should change it.</value>
<value>K úniku tohoto hesla došlo celkem {0} krát. Měli byste jej změnit.</value>
</data>
<data name="PasswordSafe" xml:space="preserve">
<value>This password was not found in any known data breaches. It should be safe to use.</value>
<value>Toto heslo nebylo nalezeno v žádném známém úniku dat. Mělo by být bezpečné ho použít.</value>
</data>
<data name="IdentityName" xml:space="preserve">
<value>Identity Name</value>
<value>Název identity</value>
</data>
<data name="Value" xml:space="preserve">
<value>Value</value>
<value>Hodnota</value>
</data>
<data name="PasswordHistory" xml:space="preserve">
<value>Password History</value>
<value>Historie hesel</value>
</data>
<data name="Types" xml:space="preserve">
<value>Types</value>
<value>Typy</value>
</data>
<data name="NoPasswordsToList" xml:space="preserve">
<value>No passwords to list.</value>
<value>Žádná hesla k zobrazení.</value>
</data>
<data name="NoItemsToList" xml:space="preserve">
<value>There are no items to list.</value>
<value>Žádné položky k zobrazení.</value>
</data>
<data name="SearchCollection" xml:space="preserve">
<value>Search collection</value>
<value>Vyledat v kolekci</value>
</data>
<data name="SearchFolder" xml:space="preserve">
<value>Search folder</value>
<value>Vyhledat ve složce</value>
</data>
<data name="SearchType" xml:space="preserve">
<value>Search type</value>
<value>Typ hledání</value>
</data>
<data name="Type" xml:space="preserve">
<value>Type</value>
<value>Typ</value>
</data>
<data name="MoveDown" xml:space="preserve">
<value>Move Down</value>
<value>Přesunout dolů</value>
</data>
<data name="MoveUp" xml:space="preserve">
<value>Move Up</value>
<value>Posunout nahoru</value>
</data>
<data name="Miscellaneous" xml:space="preserve">
<value>Miscellaneous</value>
<value>Různé</value>
</data>
<data name="Ownership" xml:space="preserve">
<value>Ownership</value>
<value>Vlastnictví</value>
</data>
<data name="WhoOwnsThisItem" xml:space="preserve">
<value>Who owns this item?</value>
<value>Kdo vlastní tuto položku?</value>
</data>
<data name="NoCollectionsToList" xml:space="preserve">
<value>There are no collections to list.</value>
<value>Žádné kolekce k zobrazení.</value>
</data>
<data name="ItemShared" xml:space="preserve">
<value>Item has been shared.</value>
<value>Položka byla sdílena.</value>
</data>
<data name="SelectOneCollection" xml:space="preserve">
<value>You must select at least one collection.</value>
<value>Musíte vybrat alespoň jednu kolekci.</value>
</data>
<data name="Share" xml:space="preserve">
<value>Share</value>
<value>Sdílet</value>
</data>
<data name="ShareItem" xml:space="preserve">
<value>Share Item</value>
<value>Sdílet položku</value>
</data>
<data name="NoOrgsToList" xml:space="preserve">
<value>No organizations to list.</value>
<value>Žádné organizace k zobrazení.</value>
</data>
<data name="ShareDesc" xml:space="preserve">
<value>Choose an organization that you wish to share this item with. Sharing transfers ownership of the item to the organization. You will no longer be the direct owner of this item once it has been shared.</value>
<value>Vyberte organizaci se kterou chcete tuto položku sdílet. Sdílení přenese vlastnictví položky na onu organizaci a již nadále nebudete přímým vlastníkem.</value>
</data>
<data name="NumberOfWords" xml:space="preserve">
<value>Number of Words</value>
<value>Počet slov</value>
</data>
<data name="Passphrase" xml:space="preserve">
<value>Passphrase</value>
<value>Heslová fráze</value>
</data>
<data name="WordSeparator" xml:space="preserve">
<value>Word Separator</value>
<value>Oddělovač slov</value>
</data>
<data name="Clear" xml:space="preserve">
<value>Clear</value>
<value>Vymazat</value>
<comment>To clear something out. example: To clear browser history.</comment>
</data>
<data name="Generator" xml:space="preserve">
<value>Generator</value>
<value>Generátor</value>
<comment>Short for "Password Generator"</comment>
</data>
<data name="NoFoldersToList" xml:space="preserve">
<value>There are no folders to list.</value>
<value>Nejsou k dispozici žádné složky k zobrazení.</value>
</data>
<data name="FingerprintPhrase" xml:space="preserve">
<value>Fingerprint Phrase</value>
<value>Fráze otisku prstu</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>
</data>
<data name="YourAccountsFingerprint" xml:space="preserve">
<value>Your account's fingerprint phrase</value>
<value>Fráze otisku prstu 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>
</data>
<data name="ShareVaultConfirmation" xml:space="preserve">
<value>Bitwarden allows you to share your vault with others by using an organization account. Would you like to visit the bitwarden.com website to learn more?</value>
<value>Bitwarden umožňuje sdílet váš trezor s ostatními prostřednictvím účtu organizace. Chcete přejít na bitwarden.com a dozvědět se víc?</value>
</data>
<data name="ExportVault" xml:space="preserve">
<value>Export Vault</value>
<value>Exportovat přihlašovací údaje</value>
</data>
<data name="LockNow" xml:space="preserve">
<value>Lock Now</value>
<value>Zamknout nyní</value>
</data>
<data name="PIN" xml:space="preserve">
<value>PIN</value>
</data>
<data name="Unlock" xml:space="preserve">
<value>Unlock</value>
<value>Odemknout</value>
</data>
<data name="LockOption30Minutes" xml:space="preserve">
<value>30 minutes</value>
<value>Po 30 minutách</value>
</data>
<data name="LockOption5Minutes" xml:space="preserve">
<value>5 minutes</value>
<value>Po 5 minutách</value>
</data>
<data name="SetPINDescription" xml:space="preserve">
<value>Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application.</value>
<value>Nastavte svůj PIN kód pro odemknutí trezoru. Pokud se zcela odhlásíte z aplikace bude váš současný PIN bude resetován.</value>
</data>
<data name="LoggedInAsOn" xml:space="preserve">
<value>Logged in as {0} on {1}.</value>
<value>Přihlášen jako {0} na {1}.</value>
<comment>ex: Logged in as user@example.com on bitwarden.com.</comment>
</data>
<data name="VaultLockedMasterPassword" xml:space="preserve">
<value>Your vault is locked. Verify your master password to continue.</value>
<value>Váš trezor je uzamčen. Pro pokračování musíte zadat hlavní heslo.</value>
</data>
<data name="VaultLockedPIN" xml:space="preserve">
<value>Your vault is locked. Verify your PIN code to continue.</value>
<value>Váš trezor je uzamčen. Pro pokračování musíte zadat PIN.</value>
</data>
<data name="Dark" xml:space="preserve">
<value>Dark</value>
<value>Tmavý</value>
<comment>A dark color</comment>
</data>
<data name="Light" xml:space="preserve">
<value>Light</value>
<value>Světlý</value>
<comment>A light color</comment>
</data>
<data name="FiveMinutes" xml:space="preserve">
<value>5 minutes</value>
<value>5 minut</value>
</data>
<data name="OneMinute" xml:space="preserve">
<value>1 minute</value>
<value>1 minuta</value>
</data>
<data name="TenSeconds" xml:space="preserve">
<value>10 seconds</value>
<value>10 sekund</value>
</data>
<data name="ThirtySeconds" xml:space="preserve">
<value>30 seconds</value>
<value>30 sekund</value>
</data>
<data name="TwentySeconds" xml:space="preserve">
<value>20 seconds</value>
<value>20 sekund</value>
</data>
<data name="TwoMinutes" xml:space="preserve">
<value>2 minutes</value>
<value>2 minuty</value>
</data>
<data name="ClearClipboard" xml:space="preserve">
<value>Clear Clipboard</value>
<value>Vymazat schránku</value>
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
</data>
<data name="ClearClipboardDescription" xml:space="preserve">
<value>Automatically clear copied values from your clipboard.</value>
<value>Automaticky smazat zkopírované hodnoty z vaší schránky.</value>
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
</data>
<data name="DefaultUriMatchDetection" xml:space="preserve">
<value>Default URI Match Detection</value>
<value>Výchozí detekce shody URI</value>
<comment>Default URI match detection for auto-fill.</comment>
</data>
<data name="DefaultUriMatchDetectionDescription" xml:space="preserve">
<value>Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill.</value>
<value>Vyberte výchozí způsob, jakým se detekuje shoda URI přihlašovacích údajů. Používá se například pro automatické vyplňování.</value>
</data>
<data name="Theme" xml:space="preserve">
<value>Theme</value>
<value>Motiv</value>
<comment>Color theme</comment>
</data>
<data name="ThemeDescription" xml:space="preserve">
<value>Change the application's color theme.</value>
<value>Změna barevného motivu aplikace.</value>
</data>
<data name="RestartIsRequired" xml:space="preserve">
<value>Restart is required.</value>
<value>Je vyžadován restart.</value>
<comment>Referring to restarting the application.</comment>
</data>
<data name="Restarting" xml:space="preserve">
<value>Restarting...</value>
<value>Restartování…</value>
</data>
<data name="CopyNotes" xml:space="preserve">
<value>Copy Notes</value>
<value>Kopírovat poznámky</value>
</data>
<data name="Exit" xml:space="preserve">
<value>Exit</value>
<value>Ukončit</value>
</data>
<data name="ExitConfirmation" xml:space="preserve">
<value>Are you sure you want to exit Bitwarden?</value>
<value>Opravdu chcete ukončit Bitwarden?</value>
</data>
<data name="PINRequireMasterPasswordRestart" xml:space="preserve">
<value>You you want to require unlocking with your master password when the application is restarted?</value>
<value>Chcete vyžadovat odemknutí hlavním heslem, když je aplikace restartována?</value>
</data>
<data name="Black" xml:space="preserve">
<value>Black</value>
<value>Černá</value>
<comment>The color black</comment>
</data>
<data name="BlacklistedUris" xml:space="preserve">
<value>Blacklisted URIs</value>
<value>URI na černé listině</value>
</data>
<data name="BlacklistedUrisDescription" xml:space="preserve">
<value>URIs that are blacklisted will not offer auto-fill. The list of apps should be comma separated. Ex: "https://twitter.com, androidapp://com.twitter.android".</value>
</data>
<data name="DisableSavePrompt" xml:space="preserve">
<value>Disable Save Prompt</value>
<value>Zakázat výzvu o uložení</value>
</data>
<data name="DisableSavePromptDescription" xml:space="preserve">
<value>The "Save Prompt" automatically prompts you to save new items to your vault whenever you enter them for the first time.</value>
<value>"Výzva k uložení" vás automaticky vyzve k uložení nových položek do trezoru, kdykoli je zadáte poprvé.</value>
</data>
<data name="LockOptionOnRestart" xml:space="preserve">
<value>On App Restart</value>
<value>Při restartu aplikace</value>
</data>
<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>Automatické vyplňování usnadňuje bezpečný přístup k trezoru Bitwarden z jiných webových stránek a aplikací. Vypadá to, že jste službu Bitwarden nepovolili. Povolte automatické vyplnění pro Bitwarden z obrazovky "Nastavení".</value>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Your theme changes will apply when the app is restarted.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Velká písmena na začátku slova</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Include Number</value>
</data>
</root>

View File

@@ -1542,7 +1542,7 @@
<value>Sortlistede URI'er</value>
</data>
<data name="BlacklistedUrisDescription" xml:space="preserve">
<value>Sortlistede URI'er tilbyder ikke autoudfyldning. Listen over apps skal være kommasepareret. F.eks: "https://twitter.com, androidapp: //com.twitter.android".</value>
<value>Sortlistede URI'er tilbyder ikke autoudfyldning. Listen skal være kommasepareret. F.eks: "https://twitter.com, androidapp: //com.twitter.android".</value>
</data>
<data name="DisableSavePrompt" xml:space="preserve">
<value>Deaktivér gem-forespørgsel</value>
@@ -1556,4 +1556,14 @@
<data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>Autoudfyldning gør det nemt at få en sikret adgang til din Bitwarden boks fra andre websteder og apps. Det ser ud til, at du ikke har aktiveret en autoudfyldningstjeneste for Bitwarden. Aktivér autoudfyldning for Bitwarden fra skærmen "Indstillinger".</value>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Dine temaændringer effektueres efter app-genstart.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Stort begyndelsesbogstav</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Inkludér cifre</value>
</data>
</root>

View File

@@ -1556,4 +1556,14 @@
<data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>Durch automatisches Füllen ist es leicht, auf Ihren Bitwarden Tresor von anderen Webseiten und Apps sicher zuzugreifen. Es sieht aus, als ob Sie den Automatisches Fülldienst für Bitwarden nicht aktiviert haben. Aktivieren Sie automatisches Füllen im "Einstellungen"-Bildschirm.</value>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Your theme changes will apply when the app is restarted.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Capitalize</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Include Number</value>
</data>
</root>

View File

@@ -1556,4 +1556,14 @@
<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>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Your theme changes will apply when the app is restarted.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Capitalise</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Include number</value>
</data>
</root>

View File

@@ -1556,4 +1556,14 @@
<data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>El auto-relleno facilita el acceso seguro a la caja fuerte de Bitwarden desde otros sitios web y aplicaciones. Parece que no has habilitado un servicio de autocompletado para Bitwarden. Habilita el autocompletado para Bitwarden desde la pantalla "Ajustes".</value>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Los cambios de tu tema se aplicarán al reiniciar la aplicación.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Mayúsculas iniciales</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Incluir número</value>
</data>
</root>

View File

@@ -1556,4 +1556,14 @@
<data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>Automaattäite teenus võimaldab teistes äppides Bitwardeni kirjetele hõlpsasti ligi pääseda. Paistab, et selles seadmes ei ole Bitwardeni Automaattäite teenus sisselülitatud. Saad selle sisse lülitada menüüst "Seaded".</value>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Välimuse muudatus rakendatakse äpi taaskäivitamisel.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Suurtäht</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Lisa number</value>
</data>
</root>

View File

@@ -182,18 +182,18 @@
<value>ويرايش پوشه</value>
</data>
<data name="Email" xml:space="preserve">
<value>رایانامه</value>
<value>ایمیل</value>
<comment>Short label for an email address.</comment>
</data>
<data name="EmailAddress" xml:space="preserve">
<value>آدرس رایانامه</value>
<value>آدرس ایمیل</value>
<comment>Full label for a email address.</comment>
</data>
<data name="EmailUs" xml:space="preserve">
<value>به ما رایانامه بزنید</value>
<value>ایمیل ما</value>
</data>
<data name="EmailUsDescription" xml:space="preserve">
<value>برای کمک گرفتن و گذاشتن بازخورد بصورت مستقیم به ما رایانامه ارسال کنید.</value>
<value>برای کمک گرفتن و گذاشتن بازخورد بصورت مستقیم به ما ایمیل ارسال کنید.</value>
</data>
<data name="EnterPIN" xml:space="preserve">
<value>پین کد را وارد کنید.</value>
@@ -412,7 +412,7 @@
<value>افزونه اپلیکیشن Bitwarden</value>
</data>
<data name="BitwardenAppExtensionAlert2" xml:space="preserve">
<value>The easiest way to add new logins to your vault is from the Bitwarden App Extension. Learn more about using the Bitwarden App Extension by navigating to the "Settings" screen.</value>
<value>ساده ترین روش برای افزودن اطلاعات ورود به گاوصندوق از طریق افزونه اپلیکیشن Bitwarden است. برای اطلاع بیشتر از چگونگی استفاده از افزونه اپلیکیشن مرورکردن صفحه "تنظیمات" است.</value>
</data>
<data name="BitwardenAppExtensionDescription" xml:space="preserve">
<value>با Bitwarden در سافاری و دیگر برنامه ها میتوانید از قابلیت پر کردن خودکار در ورودهایتان استفاده کنید.</value>
@@ -753,7 +753,7 @@
<value>وضعیت</value>
</data>
<data name="BitwardenAutofillServiceAlert2" xml:space="preserve">
<value>The easiest way to add new logins to your vault is from the Bitwarden Auto-fill Service. Learn more about using the Bitwarden Auto-fill Service by navigating to the "Settings" screen.</value>
<value>ساده ترین روش برای افزودن اطلاعات ورود به گاوصندوقتان از سرویس پر کردن خودکار Bitwarden است. برای اطلاعات بیشتر درباره استفاده از سرویس پر کردن خودکار Bitwarden است مرور کردن صفحه "تنظیمات" است.</value>
</data>
<data name="Autofill" xml:space="preserve">
<value>پر کردن خودکار</value>
@@ -1302,258 +1302,268 @@
<value>پرکردن خودکار کلمه عبور</value>
</data>
<data name="BitwardenAutofillAlert2" xml:space="preserve">
<value>The easiest way to add new logins to your vault is by using the Bitwarden Password AutoFill extension. Learn more about using the Bitwarden Password AutoFill extension by navigating to the "Settings" screen.</value>
<value>ساده ترین روش برای افزودن اطلاعات ورود به گاوصندوق از طریق افزونه پرکردن خودکار رمز عبور Bitwarden است. برای اطلاع بیشتر از چگونگی استفاده از پرکردن خودکار رمز عبور Bitwarden مرورکردن صفحه "تنظیمات" است.</value>
</data>
<data name="InvalidEmail" xml:space="preserve">
<value>Invalid email address.</value>
<value>آدرس ایمیل نامعتبر است.</value>
</data>
<data name="Cards" xml:space="preserve">
<value>Cards</value>
<value>کارتها</value>
</data>
<data name="Identities" xml:space="preserve">
<value>Identities</value>
<value>مشخصات</value>
</data>
<data name="Logins" xml:space="preserve">
<value>Logins</value>
<value>ورودها</value>
</data>
<data name="SecureNotes" xml:space="preserve">
<value>Secure Notes</value>
<value>یادداشت های امن</value>
</data>
<data name="AllItems" xml:space="preserve">
<value>All Items</value>
<value>تمام موارد</value>
</data>
<data name="URIs" xml:space="preserve">
<value>URIs</value>
<value>آدرس اینترنتی</value>
<comment>Plural form of a URI</comment>
</data>
<data name="CheckingPassword" xml:space="preserve">
<value>Checking password...</value>
<value>درحال بررسی گذرواژه…</value>
<comment>A loading message when doing an exposed password check.</comment>
</data>
<data name="CheckPassword" xml:space="preserve">
<value>Check if password has been exposed.</value>
<value>بررسی کنید که آیا رمز عبور افشا شده است.</value>
</data>
<data name="PasswordExposed" xml:space="preserve">
<value>This password has been exposed {0} time(s) in data breaches. You should change it.</value>
<value>این رمز عبور در رخنه داده ها {0} بار افشا شده است. باید تغییرش دهید.</value>
</data>
<data name="PasswordSafe" xml:space="preserve">
<value>This password was not found in any known data breaches. It should be safe to use.</value>
<value>این رمز عبور در هیچ رخنه داده ای شناخته نشده است. باید برای امنیت از آن استفاده کنید.</value>
</data>
<data name="IdentityName" xml:space="preserve">
<value>Identity Name</value>
<value>نام شناسایی</value>
</data>
<data name="Value" xml:space="preserve">
<value>Value</value>
<value>مقدار</value>
</data>
<data name="PasswordHistory" xml:space="preserve">
<value>Password History</value>
<value>تاریخچه رمز عبور</value>
</data>
<data name="Types" xml:space="preserve">
<value>Types</value>
<value>انواع</value>
</data>
<data name="NoPasswordsToList" xml:space="preserve">
<value>No passwords to list.</value>
<value>رمزعبوری برای لیست کردن نیست.</value>
</data>
<data name="NoItemsToList" xml:space="preserve">
<value>There are no items to list.</value>
<value>هیچ موردی برای نمایش وجود ندارد.</value>
</data>
<data name="SearchCollection" xml:space="preserve">
<value>Search collection</value>
<value>جستجوی مجموعه</value>
</data>
<data name="SearchFolder" xml:space="preserve">
<value>Search folder</value>
<value>جستجوی پوشه</value>
</data>
<data name="SearchType" xml:space="preserve">
<value>Search type</value>
<value>نوع جستجو</value>
</data>
<data name="Type" xml:space="preserve">
<value>Type</value>
<value>نوع</value>
</data>
<data name="MoveDown" xml:space="preserve">
<value>Move Down</value>
<value>انتقال به پایین</value>
</data>
<data name="MoveUp" xml:space="preserve">
<value>Move Up</value>
<value>انتقال به بالا</value>
</data>
<data name="Miscellaneous" xml:space="preserve">
<value>Miscellaneous</value>
<value>متفرقه</value>
</data>
<data name="Ownership" xml:space="preserve">
<value>Ownership</value>
<value>مالکیت</value>
</data>
<data name="WhoOwnsThisItem" xml:space="preserve">
<value>Who owns this item?</value>
<value>چه کسی مالک این مورد است؟</value>
</data>
<data name="NoCollectionsToList" xml:space="preserve">
<value>There are no collections to list.</value>
<value>هیچ مجموعه ای برای لیست کردن وجود ندارد.</value>
</data>
<data name="ItemShared" xml:space="preserve">
<value>Item has been shared.</value>
<value>مورد به اشتراک گذاشته شد.</value>
</data>
<data name="SelectOneCollection" xml:space="preserve">
<value>You must select at least one collection.</value>
<value>شما باید حداقل یک مجموعه را انتخاب کنید.</value>
</data>
<data name="Share" xml:space="preserve">
<value>Share</value>
<value>اشتراک گذاری</value>
</data>
<data name="ShareItem" xml:space="preserve">
<value>Share Item</value>
<value>اشتراک گذاری مورد</value>
</data>
<data name="NoOrgsToList" xml:space="preserve">
<value>No organizations to list.</value>
<value>هیچ تشکیلاتی برای لیست کردن نیست.</value>
</data>
<data name="ShareDesc" xml:space="preserve">
<value>Choose an organization that you wish to share this item with. Sharing transfers ownership of the item to the organization. You will no longer be the direct owner of this item once it has been shared.</value>
<value>تشکیلاتی که میخواهید این مورد را با آن به اشتراک بگذارید انتخاب کنید. پس از اشتراک گذاری مالکیت موارد به آن تشکیلات انتقال می یابد. شما دیگر نمی توانید صاحب اصلی این مورد پس از اشتراک گذاری آن باشید.</value>
</data>
<data name="NumberOfWords" xml:space="preserve">
<value>Number of Words</value>
<value>تعداد کلمات</value>
</data>
<data name="Passphrase" xml:space="preserve">
<value>Passphrase</value>
<value>کلمه عبور</value>
</data>
<data name="WordSeparator" xml:space="preserve">
<value>Word Separator</value>
<value>کلمه جداکننده</value>
</data>
<data name="Clear" xml:space="preserve">
<value>Clear</value>
<value>پاک کردن</value>
<comment>To clear something out. example: To clear browser history.</comment>
</data>
<data name="Generator" xml:space="preserve">
<value>Generator</value>
<value>تولید کننده</value>
<comment>Short for "Password Generator"</comment>
</data>
<data name="NoFoldersToList" xml:space="preserve">
<value>There are no folders to list.</value>
<value>هیچ پوشه ای برای لیست شدن وجود ندارد.</value>
</data>
<data name="FingerprintPhrase" xml:space="preserve">
<value>Fingerprint Phrase</value>
<value>عبارت اثر انگشت</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>
</data>
<data name="YourAccountsFingerprint" xml:space="preserve">
<value>Your account's fingerprint phrase</value>
<value>عبارت اثر انگشت حساب شما</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>
</data>
<data name="ShareVaultConfirmation" xml:space="preserve">
<value>Bitwarden allows you to share your vault with others by using an organization account. Would you like to visit the bitwarden.com website to learn more?</value>
<value>Bitwarden به شما اجازه می دهد با استفاده از سازماندهی حساب، گاوصندوقهای خود را با دیگران به اشتراک بگذارید. آیا مایل به بازدید از وب سایت bitwarden.com برای کسب اطلاعات بیشتر هستید؟</value>
</data>
<data name="ExportVault" xml:space="preserve">
<value>Export Vault</value>
<value>صادر کردن گاوصندوق</value>
</data>
<data name="LockNow" xml:space="preserve">
<value>Lock Now</value>
<value>الان قفل شود</value>
</data>
<data name="PIN" xml:space="preserve">
<value>PIN</value>
<value>پین</value>
</data>
<data name="Unlock" xml:space="preserve">
<value>Unlock</value>
<value>باز کردن قفل</value>
</data>
<data name="LockOption30Minutes" xml:space="preserve">
<value>30 minutes</value>
<value>۳۰ دقیقه</value>
</data>
<data name="LockOption5Minutes" xml:space="preserve">
<value>5 minutes</value>
<value>۵ دقیقه</value>
</data>
<data name="SetPINDescription" xml:space="preserve">
<value>Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application.</value>
<value>پین کد خود را برای باز کردن بیت واردن خود استفاده کنید. اگر به صورت کامل از حساب خود خارج شوید تنظیمات پین شما ریست می شود.</value>
</data>
<data name="LoggedInAsOn" xml:space="preserve">
<value>Logged in as {0} on {1}.</value>
<value>وارد شده به عنوان {0} در {1}.</value>
<comment>ex: Logged in as user@example.com on bitwarden.com.</comment>
</data>
<data name="VaultLockedMasterPassword" xml:space="preserve">
<value>Your vault is locked. Verify your master password to continue.</value>
<value>گاوصندوق شما فقل شد. برای ادامه گذرواژه اصلی را وارد کنید.</value>
</data>
<data name="VaultLockedPIN" xml:space="preserve">
<value>Your vault is locked. Verify your PIN code to continue.</value>
<value>گاوصندوق شما قفل شده است. برای ادامه کد پین خود را تایید کنید.</value>
</data>
<data name="Dark" xml:space="preserve">
<value>Dark</value>
<value>تاریک</value>
<comment>A dark color</comment>
</data>
<data name="Light" xml:space="preserve">
<value>Light</value>
<value>روشن</value>
<comment>A light color</comment>
</data>
<data name="FiveMinutes" xml:space="preserve">
<value>5 minutes</value>
<value>۵ دقیقه</value>
</data>
<data name="OneMinute" xml:space="preserve">
<value>1 minute</value>
<value>۱ دقیقه</value>
</data>
<data name="TenSeconds" xml:space="preserve">
<value>10 seconds</value>
<value>۱۰ ثانیه</value>
</data>
<data name="ThirtySeconds" xml:space="preserve">
<value>30 seconds</value>
<value>۳۰ ثانیه</value>
</data>
<data name="TwentySeconds" xml:space="preserve">
<value>20 seconds</value>
<value>۲۰ ثانیه</value>
</data>
<data name="TwoMinutes" xml:space="preserve">
<value>2 minutes</value>
<value>۲ دقیقه</value>
</data>
<data name="ClearClipboard" xml:space="preserve">
<value>Clear Clipboard</value>
<value>پاکسازی کلیپ‌ بورد</value>
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
</data>
<data name="ClearClipboardDescription" xml:space="preserve">
<value>Automatically clear copied values from your clipboard.</value>
<value>به صورت خودکار، مقادیر کپی شده را از کلیپ‌برد پاک کن.</value>
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
</data>
<data name="DefaultUriMatchDetection" xml:space="preserve">
<value>Default URI Match Detection</value>
<value>بازرسی تطابق URL پیشفرض</value>
<comment>Default URI match detection for auto-fill.</comment>
</data>
<data name="DefaultUriMatchDetectionDescription" xml:space="preserve">
<value>Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill.</value>
<value>روش پیش فرض اعمال بازرسی تطابق URL را هنگامی که عملی را مثل پر کردن خودکار انتخاب کنید.</value>
</data>
<data name="Theme" xml:space="preserve">
<value>Theme</value>
<value>پوسته</value>
<comment>Color theme</comment>
</data>
<data name="ThemeDescription" xml:space="preserve">
<value>Change the application's color theme.</value>
<value>تغییر رنگ پوسته برنامه.</value>
</data>
<data name="RestartIsRequired" xml:space="preserve">
<value>Restart is required.</value>
<value>راه اندازی مجدد لازم است.</value>
<comment>Referring to restarting the application.</comment>
</data>
<data name="Restarting" xml:space="preserve">
<value>Restarting...</value>
<value>راه اندازی مجدد...</value>
</data>
<data name="CopyNotes" xml:space="preserve">
<value>Copy Notes</value>
<value>کپی یادداشتها</value>
</data>
<data name="Exit" xml:space="preserve">
<value>Exit</value>
<value>خروج</value>
</data>
<data name="ExitConfirmation" xml:space="preserve">
<value>Are you sure you want to exit Bitwarden?</value>
<value>آیا مطمئنید که میخواهید از Bitwarden خارج شوید؟</value>
</data>
<data name="PINRequireMasterPasswordRestart" xml:space="preserve">
<value>You you want to require unlocking with your master password when the application is restarted?</value>
</data>
<data name="Black" xml:space="preserve">
<value>Black</value>
<value>سیاه</value>
<comment>The color black</comment>
</data>
<data name="BlacklistedUris" xml:space="preserve">
<value>Blacklisted URIs</value>
<value>فهرست سیاه آدرس های اینترنتی</value>
</data>
<data name="BlacklistedUrisDescription" xml:space="preserve">
<value>URIs that are blacklisted will not offer auto-fill. The list of apps should be comma separated. Ex: "https://twitter.com, androidapp://com.twitter.android".</value>
</data>
<data name="DisableSavePrompt" xml:space="preserve">
<value>Disable Save Prompt</value>
<value>غیر فعال کردن ذخیره سریع</value>
</data>
<data name="DisableSavePromptDescription" xml:space="preserve">
<value>The "Save Prompt" automatically prompts you to save new items to your vault whenever you enter them for the first time.</value>
<value>"ذخیره سریع" به صورت خودکار باعث افزایش سرعت شما برای ذخیره موارد جدید در گاوصندوقتان می شود زمانی که شما آنها را برای اولین بار وارد میکند.</value>
</data>
<data name="LockOptionOnRestart" xml:space="preserve">
<value>On App Restart</value>
<value>راه اندازی مجدد در برنامه</value>
</data>
<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>پرکردن خودکار دسترسی ایمن به گاوصندوق Bitwarden شما را از سایر وبسایت ها و برنامه ها آسان تر میکند. بنظر میرسد که سرویس پرکردن خودکار را برای Bitwarden فعال نکرده اید. از صفحه "تنظیمات" Bitwarden پرکردن خودکار رافعال کنید.</value>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>تغییرات شما در ظاهر برنامه بعد از اینکه برنامه را دوباره آغاز کردید اعمال می‌شود.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>بزرگ نوشتن حرف اول</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>شامل عدد</value>
</data>
</root>

View File

@@ -412,7 +412,7 @@
<value>Bitwarden-sovelluslaajennus</value>
</data>
<data name="BitwardenAppExtensionAlert2" xml:space="preserve">
<value>The easiest way to add new logins to your vault is from the Bitwarden App Extension. Learn more about using the Bitwarden App Extension by navigating to the "Settings" screen.</value>
<value>Helpoin tapa lisätä uusia kirjautumistietoja holviisi on käyttää Bitwardenin sovelluslaajennusta. Lue lisää sovelluslaajennuksesta "Työkalut"-kohdassa.</value>
</data>
<data name="BitwardenAppExtensionDescription" xml:space="preserve">
<value>Käytä bitwardenia Safarissa ja muissa sovelluksissa kirjautumistietojen automaattiseen täydennykseen.</value>
@@ -753,7 +753,7 @@
<value>Tila</value>
</data>
<data name="BitwardenAutofillServiceAlert2" xml:space="preserve">
<value>The easiest way to add new logins to your vault is from the Bitwarden Auto-fill Service. Learn more about using the Bitwarden Auto-fill Service by navigating to the "Settings" screen.</value>
<value>Helpoin tapa lisätä uusia kirjautumistietoja holviisi on käyttää Bitwardenin automaattista täydennystä. Lue lisää täydennyspalvelusta "Työkalut"-kohdassa.</value>
</data>
<data name="Autofill" xml:space="preserve">
<value>Täytä automaattisesti</value>
@@ -1236,10 +1236,10 @@
<comment>URI match detection for auto-fill.</comment>
</data>
<data name="YesAndSave" xml:space="preserve">
<value>Yes, and Save</value>
<value>Kyllä, ja tallenna</value>
</data>
<data name="AutofillAndSave" xml:space="preserve">
<value>Auto-fill and save</value>
<value>Täydennä automaattisesti ja tallenna</value>
</data>
<data name="Organization" xml:space="preserve">
<value>Organisaatio</value>
@@ -1252,10 +1252,10 @@
<value>Yritä uudelleen</value>
</data>
<data name="YubiKeyInstructionIos" xml:space="preserve">
<value>To continue, hold your YubiKey NEO against the back of the device.</value>
<value>Pidä YubiKey NEOta laitteen takaosaa vasten jatkaaksesi.</value>
</data>
<data name="BitwardenAutofillAccessibilityServiceDescription2" xml:space="preserve">
<value>The accessibility service may be helpful to use when apps do not support the standard auto-fill service.</value>
<value>Esteettömyyspalvelu voi olla hyödyllinen sovellusten jotka eivät tue standardia automaattitäyttöpalvelua kanssa.</value>
</data>
<data name="DatePasswordUpdated" xml:space="preserve">
<value>Salasana päivitetty</value>
@@ -1266,10 +1266,10 @@
<comment>ex. Date this item was updated</comment>
</data>
<data name="AutofillActivated" xml:space="preserve">
<value>AutoFill Activated!</value>
<value>Automaattinen täyttö kytketty päälle!</value>
</data>
<data name="MustLogInMainAppAutofill" xml:space="preserve">
<value>You must log into the main Bitwarden app before you can use AutoFill.</value>
<value>Sinun on kirjauduttava Bitwardenin pääsovellukseen ennen kuin voit käyttää automaattista täydennystä.</value>
</data>
<data name="AutofillSetup" xml:space="preserve">
<value>Your logins are now easily accessable right from your keyboard while logging into apps and websites.</value>
@@ -1284,7 +1284,7 @@
<value>To enable password autofill on your device, follow these instructions:</value>
</data>
<data name="AutofillTurnOn1" xml:space="preserve">
<value>1. Go to the iOS "Settings" app</value>
<value>1. Siirry iOS:n Asetukset-sovellukseen</value>
</data>
<data name="AutofillTurnOn2" xml:space="preserve">
<value>2. Tap "Passwords &amp; Accounts"</value>
@@ -1293,267 +1293,277 @@
<value>3. Tap "AutoFill Passwords"</value>
</data>
<data name="AutofillTurnOn4" xml:space="preserve">
<value>4. Turn on AutoFill</value>
<value>4. Kytke automaattinen täyttö päälle</value>
</data>
<data name="AutofillTurnOn5" xml:space="preserve">
<value>5. Select "Bitwarden"</value>
<value>5. Valitse Bitwarden</value>
</data>
<data name="PasswordAutofill" xml:space="preserve">
<value>Password AutoFill</value>
<value>Salasanojen automaattitäyttö</value>
</data>
<data name="BitwardenAutofillAlert2" xml:space="preserve">
<value>The easiest way to add new logins to your vault is by using the Bitwarden Password AutoFill extension. Learn more about using the Bitwarden Password AutoFill extension by navigating to the "Settings" screen.</value>
<value>Helpoin tapa lisätä uusia kirjautumistietoja holviisi on käyttää Bitwardenin sovelluslaajennusta. Lue lisää sovelluslaajennuksesta "Työkalut"-kohdassa.</value>
</data>
<data name="InvalidEmail" xml:space="preserve">
<value>Invalid email address.</value>
<value>Virheellinen sähköpostiosoite.</value>
</data>
<data name="Cards" xml:space="preserve">
<value>Cards</value>
<value>Kortit</value>
</data>
<data name="Identities" xml:space="preserve">
<value>Identities</value>
<value>Henkilöllisyydet</value>
</data>
<data name="Logins" xml:space="preserve">
<value>Logins</value>
<value>Kirjautumiset</value>
</data>
<data name="SecureNotes" xml:space="preserve">
<value>Secure Notes</value>
<value>Salatut muistiinpanot</value>
</data>
<data name="AllItems" xml:space="preserve">
<value>All Items</value>
<value>Kaikki kohteet</value>
</data>
<data name="URIs" xml:space="preserve">
<value>URIs</value>
<value>URIt</value>
<comment>Plural form of a URI</comment>
</data>
<data name="CheckingPassword" xml:space="preserve">
<value>Checking password...</value>
<value>Tarkistetaan salasanaa...</value>
<comment>A loading message when doing an exposed password check.</comment>
</data>
<data name="CheckPassword" xml:space="preserve">
<value>Check if password has been exposed.</value>
<value>Tarkista, onko salasana vuotanut.</value>
</data>
<data name="PasswordExposed" xml:space="preserve">
<value>This password has been exposed {0} time(s) in data breaches. You should change it.</value>
<value>Tämä salasana on paljastunut {0} tietovuodossa. Sinun kannattaa vaihtaa se.</value>
</data>
<data name="PasswordSafe" xml:space="preserve">
<value>This password was not found in any known data breaches. It should be safe to use.</value>
<value>Tätä salasanaa ei löytynyt yhdestäkään tunnetusta tietovuodosta. Sen pitäisi olla turvallinen.</value>
</data>
<data name="IdentityName" xml:space="preserve">
<value>Identity Name</value>
<value>Henkilöllisyyden nimi</value>
</data>
<data name="Value" xml:space="preserve">
<value>Value</value>
<value>Arvo</value>
</data>
<data name="PasswordHistory" xml:space="preserve">
<value>Password History</value>
<value>Salasanahistoria</value>
</data>
<data name="Types" xml:space="preserve">
<value>Types</value>
<value>Tyypit</value>
</data>
<data name="NoPasswordsToList" xml:space="preserve">
<value>No passwords to list.</value>
<value>Ei listattavia salasanoja.</value>
</data>
<data name="NoItemsToList" xml:space="preserve">
<value>There are no items to list.</value>
<value>Ei näytettäviä kohteita.</value>
</data>
<data name="SearchCollection" xml:space="preserve">
<value>Search collection</value>
<value>Hae kokoelmasta</value>
</data>
<data name="SearchFolder" xml:space="preserve">
<value>Search folder</value>
<value>Hae kansiosta</value>
</data>
<data name="SearchType" xml:space="preserve">
<value>Search type</value>
<value>Hakutyyppi</value>
</data>
<data name="Type" xml:space="preserve">
<value>Type</value>
<value>Tyyppi</value>
</data>
<data name="MoveDown" xml:space="preserve">
<value>Move Down</value>
<value>Siirrä alas</value>
</data>
<data name="MoveUp" xml:space="preserve">
<value>Move Up</value>
<value>Siirrä ylös</value>
</data>
<data name="Miscellaneous" xml:space="preserve">
<value>Miscellaneous</value>
<value>Sekalainen</value>
</data>
<data name="Ownership" xml:space="preserve">
<value>Ownership</value>
<value>Omistajuus</value>
</data>
<data name="WhoOwnsThisItem" xml:space="preserve">
<value>Who owns this item?</value>
<value>Kuka omistaa tämän kohteen?</value>
</data>
<data name="NoCollectionsToList" xml:space="preserve">
<value>There are no collections to list.</value>
<value>Ei kokoelmia listattavaksi.</value>
</data>
<data name="ItemShared" xml:space="preserve">
<value>Item has been shared.</value>
<value>Kohde jaettu.</value>
</data>
<data name="SelectOneCollection" xml:space="preserve">
<value>You must select at least one collection.</value>
<value>Valitse vähintään yksi kokoelma.</value>
</data>
<data name="Share" xml:space="preserve">
<value>Share</value>
<value>Jaa</value>
</data>
<data name="ShareItem" xml:space="preserve">
<value>Share Item</value>
<value>Jaa kohde</value>
</data>
<data name="NoOrgsToList" xml:space="preserve">
<value>No organizations to list.</value>
<value>Ei listattavia organisaatioita.</value>
</data>
<data name="ShareDesc" xml:space="preserve">
<value>Choose an organization that you wish to share this item with. Sharing transfers ownership of the item to the organization. You will no longer be the direct owner of this item once it has been shared.</value>
<value>Valitse organisaatio, jonka kanssa haluat jakaa tämän kohteen. Jakaminen siirtää kohteen omistajuuden organisaatiolle. Kohteen jakamisen jälkeen et ole enää kohteen suora omistaja.</value>
</data>
<data name="NumberOfWords" xml:space="preserve">
<value>Number of Words</value>
<value>Sanojen määrä</value>
</data>
<data name="Passphrase" xml:space="preserve">
<value>Passphrase</value>
<value>Tunnuslause</value>
</data>
<data name="WordSeparator" xml:space="preserve">
<value>Word Separator</value>
<value>Sanaerotin</value>
</data>
<data name="Clear" xml:space="preserve">
<value>Clear</value>
<value>Tyhjennä</value>
<comment>To clear something out. example: To clear browser history.</comment>
</data>
<data name="Generator" xml:space="preserve">
<value>Generator</value>
<value>Generaattori</value>
<comment>Short for "Password Generator"</comment>
</data>
<data name="NoFoldersToList" xml:space="preserve">
<value>There are no folders to list.</value>
<value>Ei kansioita näytettäväksi.</value>
</data>
<data name="FingerprintPhrase" xml:space="preserve">
<value>Fingerprint Phrase</value>
<value>Tunnistelauseke</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>
</data>
<data name="YourAccountsFingerprint" xml:space="preserve">
<value>Your account's fingerprint phrase</value>
<value>Tilisi tunnistelauseke</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>
</data>
<data name="ShareVaultConfirmation" xml:space="preserve">
<value>Bitwarden allows you to share your vault with others by using an organization account. Would you like to visit the bitwarden.com website to learn more?</value>
<value>Voit jakaa Bitwardenilla holvisi sisällön muiden kanssa käyttämällä organisaatiotiliä. Haluatko käydä bitwarden.com-sivustolla lukemassa lisää?</value>
</data>
<data name="ExportVault" xml:space="preserve">
<value>Export Vault</value>
<value>Vie holvi</value>
</data>
<data name="LockNow" xml:space="preserve">
<value>Lock Now</value>
<value>Lukitse nyt</value>
</data>
<data name="PIN" xml:space="preserve">
<value>PIN</value>
</data>
<data name="Unlock" xml:space="preserve">
<value>Unlock</value>
<value>Avaa</value>
</data>
<data name="LockOption30Minutes" xml:space="preserve">
<value>30 minutes</value>
<value>30 minuuttia</value>
</data>
<data name="LockOption5Minutes" xml:space="preserve">
<value>5 minutes</value>
<value>5 minuuttia</value>
</data>
<data name="SetPINDescription" xml:space="preserve">
<value>Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application.</value>
<value>Aseta PIN-koodi Bitwardenin avaamista varten. PIN-asetukset nollautuvat, jos kirjaudut täysin ulos sovelluksesta.</value>
</data>
<data name="LoggedInAsOn" xml:space="preserve">
<value>Logged in as {0} on {1}.</value>
<value>{0} kirjattu sivustolle {1}.</value>
<comment>ex: Logged in as user@example.com on bitwarden.com.</comment>
</data>
<data name="VaultLockedMasterPassword" xml:space="preserve">
<value>Your vault is locked. Verify your master password to continue.</value>
<value>Holvisi on lukittu. Varmista pääsalasanasi jatkaaksesi.</value>
</data>
<data name="VaultLockedPIN" xml:space="preserve">
<value>Your vault is locked. Verify your PIN code to continue.</value>
<value>Holvisi on lukittu. Vahvista PIN-koodisi jatkaaksesi.</value>
</data>
<data name="Dark" xml:space="preserve">
<value>Dark</value>
<value>Tumma</value>
<comment>A dark color</comment>
</data>
<data name="Light" xml:space="preserve">
<value>Light</value>
<value>Vaalea</value>
<comment>A light color</comment>
</data>
<data name="FiveMinutes" xml:space="preserve">
<value>5 minutes</value>
<value>5 minuuttia</value>
</data>
<data name="OneMinute" xml:space="preserve">
<value>1 minute</value>
<value>1 minuutti</value>
</data>
<data name="TenSeconds" xml:space="preserve">
<value>10 seconds</value>
<value>10 sekuntia</value>
</data>
<data name="ThirtySeconds" xml:space="preserve">
<value>30 seconds</value>
<value>30 sekuntia</value>
</data>
<data name="TwentySeconds" xml:space="preserve">
<value>20 seconds</value>
<value>20 sekuntia</value>
</data>
<data name="TwoMinutes" xml:space="preserve">
<value>2 minutes</value>
<value>2 minuuttia</value>
</data>
<data name="ClearClipboard" xml:space="preserve">
<value>Clear Clipboard</value>
<value>Tyhjennä leikepöytä</value>
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
</data>
<data name="ClearClipboardDescription" xml:space="preserve">
<value>Automatically clear copied values from your clipboard.</value>
<value>Poista kopioidut tekstit leikepöydältä automaattisesti.</value>
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
</data>
<data name="DefaultUriMatchDetection" xml:space="preserve">
<value>Default URI Match Detection</value>
<value>URIn oletustunnistustapa</value>
<comment>Default URI match detection for auto-fill.</comment>
</data>
<data name="DefaultUriMatchDetectionDescription" xml:space="preserve">
<value>Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill.</value>
<value>Valitse oletustapa, jolla URIen tunnistaminen tehdään esimerkiksi automaattisen täytön yhteydessä.</value>
</data>
<data name="Theme" xml:space="preserve">
<value>Theme</value>
<value>Teema</value>
<comment>Color theme</comment>
</data>
<data name="ThemeDescription" xml:space="preserve">
<value>Change the application's color theme.</value>
<value>Vaihda sovelluksen väriteemaa.</value>
</data>
<data name="RestartIsRequired" xml:space="preserve">
<value>Restart is required.</value>
<value>Uudelleenkäynnistys vaaditaan.</value>
<comment>Referring to restarting the application.</comment>
</data>
<data name="Restarting" xml:space="preserve">
<value>Restarting...</value>
<value>Käynnistetään uudelleen...</value>
</data>
<data name="CopyNotes" xml:space="preserve">
<value>Copy Notes</value>
<value>Kopioi muistiinpano</value>
</data>
<data name="Exit" xml:space="preserve">
<value>Exit</value>
<value>Poistu</value>
</data>
<data name="ExitConfirmation" xml:space="preserve">
<value>Are you sure you want to exit Bitwarden?</value>
<value>Oletko varma, että haluat poistua Bitwardenista?</value>
</data>
<data name="PINRequireMasterPasswordRestart" xml:space="preserve">
<value>You you want to require unlocking with your master password when the application is restarted?</value>
</data>
<data name="Black" xml:space="preserve">
<value>Black</value>
<value>Musta</value>
<comment>The color black</comment>
</data>
<data name="BlacklistedUris" xml:space="preserve">
<value>Blacklisted URIs</value>
<value>Mustalistatut URIt</value>
</data>
<data name="BlacklistedUrisDescription" xml:space="preserve">
<value>URIs that are blacklisted will not offer auto-fill. The list of apps should be comma separated. Ex: "https://twitter.com, androidapp://com.twitter.android".</value>
</data>
<data name="DisableSavePrompt" xml:space="preserve">
<value>Disable Save Prompt</value>
<value>Kytke tallennuskehote pois</value>
</data>
<data name="DisableSavePromptDescription" xml:space="preserve">
<value>The "Save Prompt" automatically prompts you to save new items to your vault whenever you enter them for the first time.</value>
<value>Tallennuskehote kysyy, haluatko tallentaa kirjautumistiedot holviisi, kun kirjaudut sivustoille ensimmäistä kertaa.</value>
</data>
<data name="LockOptionOnRestart" xml:space="preserve">
<value>On App Restart</value>
<value>Ohjelman uudelleenkäynnistyksen yhteydessä</value>
</data>
<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>Automaattinen täyttö tekee Bitwarden-holviiisi pääsystä muista ohjelmista ja sivustoista helppoa. Et näytä kytkeneen automaattista täyttöä päälle. Voit tehdä sen Asetukset-näytöstä.</value>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Your theme changes will apply when the app is restarted.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Capitalize</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Include Number</value>
</data>
</root>

View File

@@ -1542,7 +1542,7 @@
<value>URIs sur liste noire</value>
</data>
<data name="BlacklistedUrisDescription" xml:space="preserve">
<value>Les URI qui sont sur la liste noire n'offriront pas de remplissage automatique. La liste des applications doit être séparée par des virgules. Ex : "https://twitter.com, androidapp://com.twitter.android".</value>
<value>Les URI qui sont sur la liste noire n'offriront pas de remplissage automatique. La liste doit être séparée par des virgules. Ex : "https://twitter.com, androidapp://com.twitter.android".</value>
</data>
<data name="DisableSavePrompt" xml:space="preserve">
<value>Désactiver la demande d'enregistrement</value>
@@ -1556,4 +1556,14 @@
<data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>Le remplissage automatique permet d'accéder facilement à votre coffre Bitwarden depuis d'autres sites et applications. Il semble que vous n'ayez pas activé de service de remplissage automatique pour Bitwarden. Activez le remplissage automatique pour Bitwarden à partir de l'écran "Paramètres".</value>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Vos modifications de thème s'appliqueront lorsque l'application sera redémarrée.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Mettre la première lettre de chaque mot en majuscule</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Inclure un chiffre</value>
</data>
</root>

View File

@@ -1557,4 +1557,14 @@ Bitwarden בעזרת פתיחת חלון "הגדרות".</value>
<data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>השלמה אוטומטית הופכת את תהליך הכניסה לאתרים לקל ומאובטח בעת גישה לאתרים ואפליקציות. נראה שלא הפעלת את שירות ההשלמה האוטומטית עבור Bitwarden. אנא הפעל את השירות דרך חלון "הגדרות".</value>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>שינוי בערכת הנושא יוחל בהפעלה הבאה של האפליקציה.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>הפוך לאותיות גדולות</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>כלול מספרים</value>
</data>
</root>

View File

@@ -1556,4 +1556,14 @@
<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>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Your theme changes will apply when the app is restarted.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Capitalize</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Include Number</value>
</data>
</root>

View File

@@ -1556,4 +1556,14 @@
<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>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Your theme changes will apply when the app is restarted.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Capitalize</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Include Number</value>
</data>
</root>

View File

@@ -1556,4 +1556,14 @@
<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>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Your theme changes will apply when the app is restarted.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Capitalize</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Include Number</value>
</data>
</root>

View File

@@ -1556,4 +1556,14 @@
<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>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Your theme changes will apply when the app is restarted.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Capitalize</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Include Number</value>
</data>
</root>

View File

@@ -1556,4 +1556,14 @@
<data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>Auto-riempimento rende facile accedere in modo sicuro alla tua cassaforte Bitwarden da altri siti web e applicazioni. Sembra che tu non abbia abilitato un servizio di auto-riempimento per Bitwarden. Abilita l'auto-riempimento per Bitwarden dalla schermata "Impostazioni".</value>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Le modifiche del tema verranno applicate quando l'app verrà riavviata.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Rendi maiuscolo</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Includi numero</value>
</data>
</root>

View File

@@ -1556,4 +1556,14 @@
<data name="AutofillServiceNotEnabled" xml:space="preserve">
<value>自動入力を使うと、他のウェブサイトやアプリから Bitwarden 保管庫に、より安全・簡単にアクセスできます。現在 Bitwarden の自動入力サービスを有効にしていないようです。設定画面で自動入力を有効化できます。</value>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>アプリを再起動するとテーマの変更が反映されます。</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>先頭を大文字</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>数字を含む</value>
</data>
</root>

View File

@@ -1556,4 +1556,14 @@
<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>
</data>
<data name="ThemeAppliedOnRestart" xml:space="preserve">
<value>Your theme changes will apply when the app is restarted.</value>
</data>
<data name="Capitalize" xml:space="preserve">
<value>Capitalize</value>
<comment>ex. Uppercase the first character of a word.</comment>
</data>
<data name="IncludeNumber" xml:space="preserve">
<value>Include Number</value>
</data>
</root>

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