Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fc8d03cc4 | ||
|
|
df77f42145 | ||
|
|
0dea5bdbea | ||
|
|
5c7f939440 | ||
|
|
09bef28362 | ||
|
|
1f0f94746b | ||
|
|
c057be17d0 | ||
|
|
301aaf9c68 | ||
|
|
ab7093f962 | ||
|
|
29b2d67fb6 | ||
|
|
d4cd2b8be8 | ||
|
|
fea94f956d | ||
|
|
a656aa21f8 | ||
|
|
3b235f2ca2 | ||
|
|
376841f619 | ||
|
|
746a7c404b | ||
|
|
2d126300d8 | ||
|
|
ed7e43ed6e | ||
|
|
7c56f1a773 | ||
|
|
6ba396440f | ||
|
|
8970525861 | ||
|
|
5a88a66709 | ||
|
|
3ae6e3ee53 | ||
|
|
5c0d4700f9 | ||
|
|
7b354f5b8c | ||
|
|
a197c0219e | ||
|
|
05f4036309 | ||
|
|
37974c7ec8 | ||
|
|
5cb3e15201 | ||
|
|
54b4766680 | ||
|
|
cc0bb65096 | ||
|
|
296c9dc055 | ||
|
|
70aa2309b7 | ||
|
|
d2468d144e | ||
|
|
ebbe704672 | ||
|
|
d146870a74 | ||
|
|
58ebabf74c | ||
|
|
8f8a3b6387 | ||
|
|
df616cfe3e | ||
|
|
dd96608bb1 | ||
|
|
264f2ab316 | ||
|
|
773f156785 | ||
|
|
7cd3e2a5b9 | ||
|
|
0ec22a4639 | ||
|
|
74ac9cbbbe | ||
|
|
0020bd0fb7 | ||
|
|
1d6ec0f953 | ||
|
|
37f05f0a12 | ||
|
|
9a22a1dbf4 | ||
|
|
b768c8b28a | ||
|
|
bcbdbb4932 | ||
|
|
04e42c4a75 | ||
|
|
6040c7768f | ||
|
|
6da0d3e88d | ||
|
|
7c6cc7b246 | ||
|
|
d5da1d6f3f | ||
|
|
de5ee90e21 | ||
|
|
8a0c9ab3db | ||
|
|
e901a1f231 | ||
|
|
e4c47aca9e | ||
|
|
a43a3db098 | ||
|
|
d651606800 |
@@ -4,7 +4,7 @@
|
||||
|
||||
# bitwarden mobile
|
||||
|
||||
<a href="https://play.google.com/store/apps/details?id=com.x8bit.bitwarden" target="_blank"><img alt="Get it on Google Play" src="https://imgur.com/YQzmZi9.png" width="153" height="46"></a> <a href="https://itunes.apple.com/us/app/bitwarden-free-password-manager/id1137397744?mt=8" target="_blank"><img src="https://imgur.com/GdGqPMY.png" width="135" height="40"></a> <a href="https://www.amazon.com/dp/B06XMYGPMV" target="_blank"><img src="https://imgur.com/f75uYeM.png" width="132" height="45"></a>
|
||||
<a href="https://play.google.com/store/apps/details?id=com.x8bit.bitwarden" target="_blank"><img alt="Get it on Google Play" src="https://imgur.com/YQzmZi9.png" width="153" height="46"></a> <a href="https://itunes.apple.com/us/app/bitwarden-free-password-manager/id1137397744?mt=8" target="_blank"><img src="https://imgur.com/GdGqPMY.png" width="135" height="40"></a>
|
||||
|
||||
The bitwarden mobile application is written in C# with Xamarin Android, Xamarin iOS, and Xamarin Forms.
|
||||
|
||||
@@ -17,8 +17,8 @@ The bitwarden mobile application is written in C# with Xamarin Android, Xamarin
|
||||
- [Visual Studio w/ Xamarin -or- Xamarin Studio](https://store.xamarin.com/)
|
||||
|
||||
By default the app is targeting the production API. If you are running the [Core](https://github.com/bitwarden/core) API locally,
|
||||
you'll need to switch the app to target your local API. Open `src/App/Utilities/ApiHttpClient.cs` and set `BaseAddress` to your local
|
||||
API instance (ex. `new Uri("http://localhost:4000")`).
|
||||
you'll need to switch the app to target your local instance. Open `src/App/Utilities/ApiHttpClient.cs` and `src/App/Utilities/IdentityHttpClient.cs` and set the `BaseAddress` to your local
|
||||
API endpoints (ex. `new Uri("http://localhost:5000")`). Alternatively, you can also adjust the environment endpoints from the environment settings page on the home screen of the app (log out).
|
||||
|
||||
After restoring the nuget packages, you can now build and run the app.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26430.13
|
||||
VisualStudioVersion = 15.0.26730.16
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Android", "src\Android\Android.csproj", "{04B18ED2-B76D-4947-8474-191F8FD2B5E0}"
|
||||
EndProject
|
||||
@@ -29,7 +29,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "google", "google", "{2E3996
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Publisher", "store\google\Publisher\Publisher.csproj", "{428CACAB-CC26-4F41-9062-1E4A9BC82640}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UWP", "src\UWP\UWP.csproj", "{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}"
|
||||
EndProject
|
||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "UWP.Images", "src\UWP.Images\UWP.Images.shproj", "{0BE54BBB-7772-4289-BD51-1FDBB0CC2446}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||
src\UWP.Images\UWP.Images.projitems*{0be54bbb-7772-4289-bd51-1fdbb0cc2446}*SharedItemsImports = 13
|
||||
src\UWP.Images\UWP.Images.projitems*{3a2d5669-ed71-4f2b-ba85-2d36baa05141}*SharedItemsImports = 4
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
|
||||
Ad-Hoc|ARM = Ad-Hoc|ARM
|
||||
@@ -94,8 +102,6 @@ Global
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.Debug|x64.Deploy.0 = Debug|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{04B18ED2-B76D-4947-8474-191F8FD2B5E0}.Debug|x86.Deploy.0 = Debug|Any CPU
|
||||
@@ -136,7 +142,6 @@ Global
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.Debug|x64.ActiveCfg = Debug|iPhone
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.Debug|x64.Build.0 = Debug|iPhone
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.Debug|x86.ActiveCfg = Debug|iPhone
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.Debug|x86.Build.0 = Debug|iPhone
|
||||
{1F78403F-9A28-405B-9289-B9DBEB55F074}.Release|Any CPU.ActiveCfg = Release|iPhone
|
||||
@@ -222,7 +227,6 @@ Global
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.Debug|iPhone.ActiveCfg = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A300DCE1-8D10-4267-B96A-CB01AEB7C220}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -258,7 +262,6 @@ Global
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.Debug|x64.ActiveCfg = Debug|iPhone
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.Debug|x64.Build.0 = Debug|iPhone
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.Debug|x86.ActiveCfg = Debug|iPhone
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.Debug|x86.Build.0 = Debug|iPhone
|
||||
{32F5A2D6-F54D-4DA1-AE26-0A980D48F422}.Release|Any CPU.ActiveCfg = Release|iPhone
|
||||
@@ -300,7 +303,6 @@ Global
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B2538ADA-B605-4D6F-ACD2-62A409680F84}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -394,8 +396,6 @@ Global
|
||||
{FA507A17-D4E3-46DF-ACD8-D7E6D7D4E3AE}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{FA507A17-D4E3-46DF-ACD8-D7E6D7D4E3AE}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU
|
||||
{FA507A17-D4E3-46DF-ACD8-D7E6D7D4E3AE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{FA507A17-D4E3-46DF-ACD8-D7E6D7D4E3AE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{FA507A17-D4E3-46DF-ACD8-D7E6D7D4E3AE}.Debug|x64.Deploy.0 = Debug|Any CPU
|
||||
{FA507A17-D4E3-46DF-ACD8-D7E6D7D4E3AE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{FA507A17-D4E3-46DF-ACD8-D7E6D7D4E3AE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{FA507A17-D4E3-46DF-ACD8-D7E6D7D4E3AE}.Debug|x86.Deploy.0 = Debug|Any CPU
|
||||
@@ -450,7 +450,6 @@ Global
|
||||
{428CACAB-CC26-4F41-9062-1E4A9BC82640}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
|
||||
{428CACAB-CC26-4F41-9062-1E4A9BC82640}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
|
||||
{428CACAB-CC26-4F41-9062-1E4A9BC82640}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{428CACAB-CC26-4F41-9062-1E4A9BC82640}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{428CACAB-CC26-4F41-9062-1E4A9BC82640}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{428CACAB-CC26-4F41-9062-1E4A9BC82640}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{428CACAB-CC26-4F41-9062-1E4A9BC82640}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -465,6 +464,66 @@ Global
|
||||
{428CACAB-CC26-4F41-9062-1E4A9BC82640}.Release|x64.Build.0 = Release|Any CPU
|
||||
{428CACAB-CC26-4F41-9062-1E4A9BC82640}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{428CACAB-CC26-4F41-9062-1E4A9BC82640}.Release|x86.Build.0 = Release|Any CPU
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|Any CPU.ActiveCfg = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|Any CPU.Build.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|Any CPU.Deploy.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|ARM.ActiveCfg = Release|ARM
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|ARM.Build.0 = Release|ARM
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|ARM.Deploy.0 = Release|ARM
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|iPhone.ActiveCfg = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|iPhone.Build.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|iPhone.Deploy.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|x64.ActiveCfg = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|x64.Build.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|x64.Deploy.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|x86.ActiveCfg = Release|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|x86.Build.0 = Release|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Ad-Hoc|x86.Deploy.0 = Release|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|Any CPU.ActiveCfg = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|Any CPU.Build.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|Any CPU.Deploy.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|ARM.ActiveCfg = Release|ARM
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|ARM.Build.0 = Release|ARM
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|ARM.Deploy.0 = Release|ARM
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|iPhone.ActiveCfg = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|iPhone.Build.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|iPhone.Deploy.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|iPhoneSimulator.ActiveCfg = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|iPhoneSimulator.Build.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|iPhoneSimulator.Deploy.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|x64.ActiveCfg = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|x64.Build.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|x64.Deploy.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|x86.ActiveCfg = Release|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|x86.Build.0 = Release|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.AppStore|x86.Deploy.0 = Release|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|iPhone.ActiveCfg = Debug|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|iPhoneSimulator.ActiveCfg = Debug|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|x64.Build.0 = Debug|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|x86.Build.0 = Debug|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|ARM.Build.0 = Release|ARM
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|iPhone.ActiveCfg = Release|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|iPhoneSimulator.ActiveCfg = Release|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|x64.ActiveCfg = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|x64.Build.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|x64.Deploy.0 = Release|x64
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|x86.ActiveCfg = Release|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|x86.Build.0 = Release|x86
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141}.Release|x86.Deploy.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -480,5 +539,10 @@ Global
|
||||
{FA507A17-D4E3-46DF-ACD8-D7E6D7D4E3AE} = {0D790714-ECF8-4A83-BE4A-E9C84DD1BB5D}
|
||||
{2E399654-26A2-46F6-B9CA-1B496A3F370A} = {92470CBD-9047-4C3C-8EA3-D972D6622D84}
|
||||
{428CACAB-CC26-4F41-9062-1E4A9BC82640} = {2E399654-26A2-46F6-B9CA-1B496A3F370A}
|
||||
{3A2D5669-ED71-4F2B-BA85-2D36BAA05141} = {EC730FD9-F623-4B6C-B503-95CDCFBCF277}
|
||||
{0BE54BBB-7772-4289-BD51-1FDBB0CC2446} = {EC730FD9-F623-4B6C-B503-95CDCFBCF277}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {318CB2DF-0118-43A3-AC83-56BADCF71CCD}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
|
||||
<AndroidLinkSkip>PushNotification.Plugin;PushNotification.Plugin.Abstractions;Xamarin.GooglePlayServices.Base;Xamarin.GooglePlayServices.Basement;Xamarin.GooglePlayServices.Measurement;Xamarin.GooglePlayServices.Gcm;BitwardenAndroid;BitwardenApp;SQLite-net;Xamarin.Android.Net</AndroidLinkSkip>
|
||||
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
|
||||
<AndroidSupportedAbis>armeabi;armeabi-v7a;x86;x86_64;arm64-v8a</AndroidSupportedAbis>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Acr.Support.Android, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
@@ -163,14 +164,6 @@
|
||||
<Reference Include="Plugin.Settings.Abstractions, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Xam.Plugins.Settings.3.0.1\lib\MonoAndroid10\Plugin.Settings.Abstractions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PushNotification.Plugin, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Xam.Plugin.PushNotification.1.2.4\lib\MonoAndroid10\PushNotification.Plugin.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="PushNotification.Plugin.Abstractions, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Xam.Plugin.PushNotification.1.2.4\lib\MonoAndroid10\PushNotification.Plugin.Abstractions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SimpleInjector, Version=4.0.8.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\SimpleInjector.4.0.8\lib\netstandard1.3\SimpleInjector.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -178,8 +171,8 @@
|
||||
<HintPath>..\..\packages\Splat.1.6.2\lib\monoandroid\Splat.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SQLite-net, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\sqlite-net-pcl.1.4.118\lib\netstandard1.1\SQLite-net.dll</HintPath>
|
||||
<Reference Include="SQLite-net, Version=1.5.166.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\sqlite-net-pcl.1.5.166-beta\lib\netstandard1.1\SQLite-net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SQLitePCLRaw.batteries_green, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a84b7dcfb1391f7f, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\SQLitePCLRaw.bundle_green.1.1.8\lib\MonoAndroid\SQLitePCLRaw.batteries_green.dll</HintPath>
|
||||
@@ -324,6 +317,7 @@
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Services\LogService.cs" />
|
||||
<Compile Include="Services\MemoryService.cs" />
|
||||
<Compile Include="Services\AndroidPushNotificationService.cs" />
|
||||
<Compile Include="Services\ReflectionService.cs" />
|
||||
<Compile Include="Services\SqlService.cs" />
|
||||
<Compile Include="SplashActivity.cs" />
|
||||
@@ -948,6 +942,126 @@
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable\shield.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable\clipboard.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable\launch.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-hdpi\clipboard.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-hdpi\launch.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xhdpi\clipboard.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xhdpi\launch.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxhdpi\clipboard.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxhdpi\launch.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxxhdpi\clipboard.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxxhdpi\launch.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable\card.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable\id.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable\login.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable\note.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-hdpi\card.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-hdpi\id.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-hdpi\note.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-hdpi\login.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xhdpi\card.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xhdpi\id.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xhdpi\note.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xhdpi\login.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxhdpi\card.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxhdpi\id.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxhdpi\login.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxhdpi\note.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxxhdpi\card.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxxhdpi\id.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxxhdpi\note.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxxhdpi\login.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxhdpi\android.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxhdpi\apple.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xhdpi\apple.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xhdpi\android.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxxhdpi\android.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-xxxhdpi\apple.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-hdpi\android.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable-hdpi\apple.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable\android.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\drawable\apple.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
<Import Project="..\..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\build\Xamarin.Android.Support.Vector.Drawable.targets" Condition="Exists('..\..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\build\Xamarin.Android.Support.Vector.Drawable.targets')" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
|
||||
@@ -55,7 +55,8 @@ namespace Bit.Android
|
||||
new Browser("com.linkbubble.playstore", "url_text"),
|
||||
new Browser("com.ksmobile.cb", "address_bar_edit_text"),
|
||||
new Browser("acr.browser.lightning", "search"),
|
||||
new Browser("acr.browser.barebones", "search")
|
||||
new Browser("acr.browser.barebones", "search"),
|
||||
new Browser("com.microsoft.emmx", "url_bar")
|
||||
}.ToDictionary(n => n.PackageName);
|
||||
|
||||
private readonly IAppSettingsService _appSettings;
|
||||
|
||||
@@ -16,6 +16,10 @@ namespace Bit.Android.Controls
|
||||
{
|
||||
Control.TextSize = (float)Device.GetNamedSize(NamedSize.Medium, typeof(Button));
|
||||
}
|
||||
|
||||
// This will prevent all screen overlay apps from being able to interact with buttons.
|
||||
// Ex: apps that change the screen color for "night mode"
|
||||
// Control.FilterTouchesWhenObscured = true;
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
|
||||
@@ -62,7 +62,8 @@ namespace Bit.Android.Controls
|
||||
|
||||
if(selected)
|
||||
{
|
||||
var selectedResource = IdFromTitle(string.Format("{0}_selected", icon), ResourceManager.DrawableClass);
|
||||
var selectedIcon = string.Format("{0}_selected", icon.Replace(".png", string.Empty));
|
||||
var selectedResource = IdFromTitle(selectedIcon, ResourceManager.DrawableClass);
|
||||
if(selectedResource != 0)
|
||||
{
|
||||
tab.SetIcon(selectedResource);
|
||||
|
||||
@@ -24,7 +24,8 @@ namespace Bit.Android
|
||||
{
|
||||
[Activity(Label = "bitwarden",
|
||||
Icon = "@drawable/icon",
|
||||
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
|
||||
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation,
|
||||
Exported = false)]
|
||||
public class MainActivity : FormsAppCompatActivity
|
||||
{
|
||||
private const string HockeyAppId = "d3834185b4a643479047b86c65293d42";
|
||||
@@ -104,7 +105,7 @@ namespace Bit.Android
|
||||
OpenAccessibilitySettings();
|
||||
});
|
||||
|
||||
MessagingCenter.Subscribe<Xamarin.Forms.Application, VaultListPageModel.Login>(
|
||||
MessagingCenter.Subscribe<Xamarin.Forms.Application, VaultListPageModel.Cipher>(
|
||||
Xamarin.Forms.Application.Current, "Autofill", (sender, args) =>
|
||||
{
|
||||
ReturnCredentials(args);
|
||||
@@ -128,10 +129,10 @@ namespace Bit.Android
|
||||
});
|
||||
}
|
||||
|
||||
private void ReturnCredentials(VaultListPageModel.Login login)
|
||||
private void ReturnCredentials(VaultListPageModel.Cipher cipher)
|
||||
{
|
||||
Intent data = new Intent();
|
||||
if(login == null)
|
||||
if(cipher == null)
|
||||
{
|
||||
data.PutExtra("canceled", "true");
|
||||
}
|
||||
@@ -139,14 +140,14 @@ namespace Bit.Android
|
||||
{
|
||||
var isPremium = Resolver.Resolve<ITokenService>()?.TokenPremium ?? false;
|
||||
var autoCopyEnabled = !_settings.GetValueOrDefault(Constants.SettingDisableTotpCopy, false);
|
||||
if(isPremium && autoCopyEnabled && _deviceActionService != null && login.Totp.Value != null)
|
||||
if(isPremium && autoCopyEnabled && _deviceActionService != null && cipher.LoginTotp?.Value != null)
|
||||
{
|
||||
_deviceActionService.CopyToClipboard(App.Utilities.Crypto.Totp(login.Totp.Value));
|
||||
_deviceActionService.CopyToClipboard(App.Utilities.Crypto.Totp(cipher.LoginTotp.Value));
|
||||
}
|
||||
|
||||
data.PutExtra("uri", login.Uri.Value);
|
||||
data.PutExtra("username", login.Username);
|
||||
data.PutExtra("password", login.Password.Value);
|
||||
data.PutExtra("uri", cipher.LoginUri);
|
||||
data.PutExtra("username", cipher.LoginUsername);
|
||||
data.PutExtra("password", cipher.LoginPassword?.Value ?? null);
|
||||
}
|
||||
|
||||
if(Parent == null)
|
||||
|
||||
@@ -12,8 +12,6 @@ using Plugin.Connectivity;
|
||||
using Plugin.CurrentActivity;
|
||||
using Plugin.Fingerprint;
|
||||
using Plugin.Settings;
|
||||
using PushNotification.Plugin;
|
||||
using PushNotification.Plugin.Abstractions;
|
||||
using XLabs.Ioc;
|
||||
using System.Threading.Tasks;
|
||||
using Plugin.Settings.Abstractions;
|
||||
@@ -69,7 +67,7 @@ namespace Bit.Android
|
||||
|
||||
private void HandlePushReregistration()
|
||||
{
|
||||
var pushNotification = Resolver.Resolve<IPushNotification>();
|
||||
var pushNotification = Resolver.Resolve<IPushNotificationService>();
|
||||
var settings = Resolver.Resolve<ISettings>();
|
||||
|
||||
// Reregister for push token based on certain conditions
|
||||
@@ -153,11 +151,11 @@ namespace Bit.Android
|
||||
|
||||
public static void StartPushService()
|
||||
{
|
||||
AppContext.StartService(new Intent(AppContext, typeof(PushNotificationService)));
|
||||
AppContext.StartService(new Intent(AppContext, typeof(AndroidPushService)));
|
||||
if(Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
|
||||
{
|
||||
PendingIntent pintent = PendingIntent.GetService(AppContext, 0, new Intent(AppContext,
|
||||
typeof(PushNotificationService)), 0);
|
||||
typeof(AndroidPushService)), 0);
|
||||
AlarmManager alarm = (AlarmManager)AppContext.GetSystemService(AlarmService);
|
||||
alarm.Cancel(pintent);
|
||||
}
|
||||
@@ -165,11 +163,11 @@ namespace Bit.Android
|
||||
|
||||
public static void StopPushService()
|
||||
{
|
||||
AppContext.StopService(new Intent(AppContext, typeof(PushNotificationService)));
|
||||
AppContext.StopService(new Intent(AppContext, typeof(AndroidPushService)));
|
||||
if(Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
|
||||
{
|
||||
PendingIntent pintent = PendingIntent.GetService(AppContext, 0, new Intent(AppContext,
|
||||
typeof(PushNotificationService)), 0);
|
||||
typeof(AndroidPushService)), 0);
|
||||
AlarmManager alarm = (AlarmManager)AppContext.GetSystemService(AlarmService);
|
||||
alarm.Cancel(pintent);
|
||||
}
|
||||
@@ -197,7 +195,7 @@ namespace Bit.Android
|
||||
container.RegisterSingleton<IKeyDerivationService, BouncyCastleKeyDerivationService>();
|
||||
container.RegisterSingleton<IAuthService, AuthService>();
|
||||
container.RegisterSingleton<IFolderService, FolderService>();
|
||||
container.RegisterSingleton<ILoginService, LoginService>();
|
||||
container.RegisterSingleton<ICipherService, CipherService>();
|
||||
container.RegisterSingleton<ISyncService, SyncService>();
|
||||
container.RegisterSingleton<IDeviceActionService, DeviceActionService>();
|
||||
container.RegisterSingleton<IAppIdService, AppIdService>();
|
||||
@@ -218,7 +216,7 @@ namespace Bit.Android
|
||||
// Repositories
|
||||
container.RegisterSingleton<IFolderRepository, FolderRepository>();
|
||||
container.RegisterSingleton<IFolderApiRepository, FolderApiRepository>();
|
||||
container.RegisterSingleton<ILoginRepository, LoginRepository>();
|
||||
container.RegisterSingleton<ICipherRepository, CipherRepository>();
|
||||
container.RegisterSingleton<IAttachmentRepository, AttachmentRepository>();
|
||||
container.RegisterSingleton<IConnectApiRepository, ConnectApiRepository>();
|
||||
container.RegisterSingleton<IDeviceApiRepository, DeviceApiRepository>();
|
||||
|
||||
@@ -15,8 +15,9 @@ namespace Bit.Android
|
||||
public override void OnReceive(Context context, Intent intent)
|
||||
{
|
||||
Debug.WriteLine("App updated!");
|
||||
Helpers.PerformUpdateTasks(Resolver.Resolve<ISettings>(), Resolver.Resolve<IAppInfoService>(),
|
||||
Resolver.Resolve<IDatabaseService>());
|
||||
Helpers.PerformUpdateTasks(Resolver.Resolve<ISettings>(),
|
||||
Resolver.Resolve<IAppInfoService>(),Resolver.Resolve<IDatabaseService>(),
|
||||
Resolver.Resolve<ISyncService>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.x8bit.bitwarden" android:versionName="1.11.0" android:installLocation="auto" android:versionCode="502" xmlns:tools="http://schemas.android.com/tools">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.x8bit.bitwarden" android:versionName="1.12.1" android:installLocation="auto" android:versionCode="502" xmlns:tools="http://schemas.android.com/tools">
|
||||
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
@@ -12,6 +12,7 @@
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
|
||||
<uses-permission android:name="com.x8bit.bitwarden.permission.C2D_MESSAGE" />
|
||||
<permission android:name="com.x8bit.bitwarden.permission.C2D_MESSAGE" android:protectionLevel="signature" />
|
||||
|
||||
<uses-feature android:name="android.hardware.camera" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
|
||||
|
||||
372
src/Android/Resources/Resource.Designer.cs
generated
@@ -2311,520 +2311,544 @@ namespace Bit.Android
|
||||
public const int accessibility_step2 = 2130837582;
|
||||
|
||||
// aapt resource value: 0x7f02004f
|
||||
public const int camera = 2130837583;
|
||||
public const int android = 2130837583;
|
||||
|
||||
// aapt resource value: 0x7f020050
|
||||
public const int cloudup = 2130837584;
|
||||
public const int apple = 2130837584;
|
||||
|
||||
// aapt resource value: 0x7f020051
|
||||
public const int cog = 2130837585;
|
||||
public const int camera = 2130837585;
|
||||
|
||||
// aapt resource value: 0x7f020052
|
||||
public const int cogs = 2130837586;
|
||||
public const int card = 2130837586;
|
||||
|
||||
// aapt resource value: 0x7f020053
|
||||
public const int cogs_selected = 2130837587;
|
||||
public const int clipboard = 2130837587;
|
||||
|
||||
// aapt resource value: 0x7f020054
|
||||
public const int common_full_open_on_phone = 2130837588;
|
||||
public const int cloudup = 2130837588;
|
||||
|
||||
// aapt resource value: 0x7f020055
|
||||
public const int common_google_signin_btn_icon_dark = 2130837589;
|
||||
public const int cog = 2130837589;
|
||||
|
||||
// aapt resource value: 0x7f020056
|
||||
public const int common_google_signin_btn_icon_dark_disabled = 2130837590;
|
||||
public const int cogs = 2130837590;
|
||||
|
||||
// aapt resource value: 0x7f020057
|
||||
public const int common_google_signin_btn_icon_dark_focused = 2130837591;
|
||||
public const int cogs_selected = 2130837591;
|
||||
|
||||
// aapt resource value: 0x7f020058
|
||||
public const int common_google_signin_btn_icon_dark_normal = 2130837592;
|
||||
public const int common_full_open_on_phone = 2130837592;
|
||||
|
||||
// aapt resource value: 0x7f020059
|
||||
public const int common_google_signin_btn_icon_dark_pressed = 2130837593;
|
||||
public const int common_google_signin_btn_icon_dark = 2130837593;
|
||||
|
||||
// aapt resource value: 0x7f02005a
|
||||
public const int common_google_signin_btn_icon_light = 2130837594;
|
||||
public const int common_google_signin_btn_icon_dark_disabled = 2130837594;
|
||||
|
||||
// aapt resource value: 0x7f02005b
|
||||
public const int common_google_signin_btn_icon_light_disabled = 2130837595;
|
||||
public const int common_google_signin_btn_icon_dark_focused = 2130837595;
|
||||
|
||||
// aapt resource value: 0x7f02005c
|
||||
public const int common_google_signin_btn_icon_light_focused = 2130837596;
|
||||
public const int common_google_signin_btn_icon_dark_normal = 2130837596;
|
||||
|
||||
// aapt resource value: 0x7f02005d
|
||||
public const int common_google_signin_btn_icon_light_normal = 2130837597;
|
||||
public const int common_google_signin_btn_icon_dark_pressed = 2130837597;
|
||||
|
||||
// aapt resource value: 0x7f02005e
|
||||
public const int common_google_signin_btn_icon_light_pressed = 2130837598;
|
||||
public const int common_google_signin_btn_icon_light = 2130837598;
|
||||
|
||||
// aapt resource value: 0x7f02005f
|
||||
public const int common_google_signin_btn_text_dark = 2130837599;
|
||||
public const int common_google_signin_btn_icon_light_disabled = 2130837599;
|
||||
|
||||
// aapt resource value: 0x7f020060
|
||||
public const int common_google_signin_btn_text_dark_disabled = 2130837600;
|
||||
public const int common_google_signin_btn_icon_light_focused = 2130837600;
|
||||
|
||||
// aapt resource value: 0x7f020061
|
||||
public const int common_google_signin_btn_text_dark_focused = 2130837601;
|
||||
public const int common_google_signin_btn_icon_light_normal = 2130837601;
|
||||
|
||||
// aapt resource value: 0x7f020062
|
||||
public const int common_google_signin_btn_text_dark_normal = 2130837602;
|
||||
public const int common_google_signin_btn_icon_light_pressed = 2130837602;
|
||||
|
||||
// aapt resource value: 0x7f020063
|
||||
public const int common_google_signin_btn_text_dark_pressed = 2130837603;
|
||||
public const int common_google_signin_btn_text_dark = 2130837603;
|
||||
|
||||
// aapt resource value: 0x7f020064
|
||||
public const int common_google_signin_btn_text_light = 2130837604;
|
||||
public const int common_google_signin_btn_text_dark_disabled = 2130837604;
|
||||
|
||||
// aapt resource value: 0x7f020065
|
||||
public const int common_google_signin_btn_text_light_disabled = 2130837605;
|
||||
public const int common_google_signin_btn_text_dark_focused = 2130837605;
|
||||
|
||||
// aapt resource value: 0x7f020066
|
||||
public const int common_google_signin_btn_text_light_focused = 2130837606;
|
||||
public const int common_google_signin_btn_text_dark_normal = 2130837606;
|
||||
|
||||
// aapt resource value: 0x7f020067
|
||||
public const int common_google_signin_btn_text_light_normal = 2130837607;
|
||||
public const int common_google_signin_btn_text_dark_pressed = 2130837607;
|
||||
|
||||
// aapt resource value: 0x7f020068
|
||||
public const int common_google_signin_btn_text_light_pressed = 2130837608;
|
||||
public const int common_google_signin_btn_text_light = 2130837608;
|
||||
|
||||
// aapt resource value: 0x7f020069
|
||||
public const int common_ic_googleplayservices = 2130837609;
|
||||
public const int common_google_signin_btn_text_light_disabled = 2130837609;
|
||||
|
||||
// aapt resource value: 0x7f02006a
|
||||
public const int common_plus_signin_btn_icon_dark = 2130837610;
|
||||
public const int common_google_signin_btn_text_light_focused = 2130837610;
|
||||
|
||||
// aapt resource value: 0x7f02006b
|
||||
public const int common_plus_signin_btn_icon_dark_disabled = 2130837611;
|
||||
public const int common_google_signin_btn_text_light_normal = 2130837611;
|
||||
|
||||
// aapt resource value: 0x7f02006c
|
||||
public const int common_plus_signin_btn_icon_dark_focused = 2130837612;
|
||||
public const int common_google_signin_btn_text_light_pressed = 2130837612;
|
||||
|
||||
// aapt resource value: 0x7f02006d
|
||||
public const int common_plus_signin_btn_icon_dark_normal = 2130837613;
|
||||
public const int common_ic_googleplayservices = 2130837613;
|
||||
|
||||
// aapt resource value: 0x7f02006e
|
||||
public const int common_plus_signin_btn_icon_dark_pressed = 2130837614;
|
||||
public const int common_plus_signin_btn_icon_dark = 2130837614;
|
||||
|
||||
// aapt resource value: 0x7f02006f
|
||||
public const int common_plus_signin_btn_icon_light = 2130837615;
|
||||
public const int common_plus_signin_btn_icon_dark_disabled = 2130837615;
|
||||
|
||||
// aapt resource value: 0x7f020070
|
||||
public const int common_plus_signin_btn_icon_light_disabled = 2130837616;
|
||||
public const int common_plus_signin_btn_icon_dark_focused = 2130837616;
|
||||
|
||||
// aapt resource value: 0x7f020071
|
||||
public const int common_plus_signin_btn_icon_light_focused = 2130837617;
|
||||
public const int common_plus_signin_btn_icon_dark_normal = 2130837617;
|
||||
|
||||
// aapt resource value: 0x7f020072
|
||||
public const int common_plus_signin_btn_icon_light_normal = 2130837618;
|
||||
public const int common_plus_signin_btn_icon_dark_pressed = 2130837618;
|
||||
|
||||
// aapt resource value: 0x7f020073
|
||||
public const int common_plus_signin_btn_icon_light_pressed = 2130837619;
|
||||
public const int common_plus_signin_btn_icon_light = 2130837619;
|
||||
|
||||
// aapt resource value: 0x7f020074
|
||||
public const int common_plus_signin_btn_text_dark = 2130837620;
|
||||
public const int common_plus_signin_btn_icon_light_disabled = 2130837620;
|
||||
|
||||
// aapt resource value: 0x7f020075
|
||||
public const int common_plus_signin_btn_text_dark_disabled = 2130837621;
|
||||
public const int common_plus_signin_btn_icon_light_focused = 2130837621;
|
||||
|
||||
// aapt resource value: 0x7f020076
|
||||
public const int common_plus_signin_btn_text_dark_focused = 2130837622;
|
||||
public const int common_plus_signin_btn_icon_light_normal = 2130837622;
|
||||
|
||||
// aapt resource value: 0x7f020077
|
||||
public const int common_plus_signin_btn_text_dark_normal = 2130837623;
|
||||
public const int common_plus_signin_btn_icon_light_pressed = 2130837623;
|
||||
|
||||
// aapt resource value: 0x7f020078
|
||||
public const int common_plus_signin_btn_text_dark_pressed = 2130837624;
|
||||
public const int common_plus_signin_btn_text_dark = 2130837624;
|
||||
|
||||
// aapt resource value: 0x7f020079
|
||||
public const int common_plus_signin_btn_text_light = 2130837625;
|
||||
public const int common_plus_signin_btn_text_dark_disabled = 2130837625;
|
||||
|
||||
// aapt resource value: 0x7f02007a
|
||||
public const int common_plus_signin_btn_text_light_disabled = 2130837626;
|
||||
public const int common_plus_signin_btn_text_dark_focused = 2130837626;
|
||||
|
||||
// aapt resource value: 0x7f02007b
|
||||
public const int common_plus_signin_btn_text_light_focused = 2130837627;
|
||||
public const int common_plus_signin_btn_text_dark_normal = 2130837627;
|
||||
|
||||
// aapt resource value: 0x7f02007c
|
||||
public const int common_plus_signin_btn_text_light_normal = 2130837628;
|
||||
public const int common_plus_signin_btn_text_dark_pressed = 2130837628;
|
||||
|
||||
// aapt resource value: 0x7f02007d
|
||||
public const int common_plus_signin_btn_text_light_pressed = 2130837629;
|
||||
public const int common_plus_signin_btn_text_light = 2130837629;
|
||||
|
||||
// aapt resource value: 0x7f02007e
|
||||
public const int design_fab_background = 2130837630;
|
||||
public const int common_plus_signin_btn_text_light_disabled = 2130837630;
|
||||
|
||||
// aapt resource value: 0x7f02007f
|
||||
public const int design_snackbar_background = 2130837631;
|
||||
public const int common_plus_signin_btn_text_light_focused = 2130837631;
|
||||
|
||||
// aapt resource value: 0x7f020080
|
||||
public const int download = 2130837632;
|
||||
public const int common_plus_signin_btn_text_light_normal = 2130837632;
|
||||
|
||||
// aapt resource value: 0x7f020081
|
||||
public const int envelope = 2130837633;
|
||||
public const int common_plus_signin_btn_text_light_pressed = 2130837633;
|
||||
|
||||
// aapt resource value: 0x7f020082
|
||||
public const int eye = 2130837634;
|
||||
public const int design_fab_background = 2130837634;
|
||||
|
||||
// aapt resource value: 0x7f020083
|
||||
public const int eye_slash = 2130837635;
|
||||
public const int design_snackbar_background = 2130837635;
|
||||
|
||||
// aapt resource value: 0x7f020084
|
||||
public const int fa_lock = 2130837636;
|
||||
public const int download = 2130837636;
|
||||
|
||||
// aapt resource value: 0x7f020085
|
||||
public const int fa_lock_selected = 2130837637;
|
||||
public const int envelope = 2130837637;
|
||||
|
||||
// aapt resource value: 0x7f020086
|
||||
public const int fingerprint = 2130837638;
|
||||
public const int eye = 2130837638;
|
||||
|
||||
// aapt resource value: 0x7f020087
|
||||
public const int fingerprint_white = 2130837639;
|
||||
public const int eye_slash = 2130837639;
|
||||
|
||||
// aapt resource value: 0x7f020088
|
||||
public const int folder = 2130837640;
|
||||
public const int fa_lock = 2130837640;
|
||||
|
||||
// aapt resource value: 0x7f020089
|
||||
public const int globe = 2130837641;
|
||||
public const int fa_lock_selected = 2130837641;
|
||||
|
||||
// aapt resource value: 0x7f02008a
|
||||
public const int hockeyapp_btn_background = 2130837642;
|
||||
public const int fingerprint = 2130837642;
|
||||
|
||||
// aapt resource value: 0x7f02008b
|
||||
public const int ic_audiotrack = 2130837643;
|
||||
public const int fingerprint_white = 2130837643;
|
||||
|
||||
// aapt resource value: 0x7f02008c
|
||||
public const int ic_audiotrack_light = 2130837644;
|
||||
public const int folder = 2130837644;
|
||||
|
||||
// aapt resource value: 0x7f02008d
|
||||
public const int ic_bluetooth_grey = 2130837645;
|
||||
public const int globe = 2130837645;
|
||||
|
||||
// aapt resource value: 0x7f02008e
|
||||
public const int ic_bluetooth_white = 2130837646;
|
||||
public const int hockeyapp_btn_background = 2130837646;
|
||||
|
||||
// aapt resource value: 0x7f02008f
|
||||
public const int ic_cast_dark = 2130837647;
|
||||
public const int ic_audiotrack = 2130837647;
|
||||
|
||||
// aapt resource value: 0x7f020090
|
||||
public const int ic_cast_disabled_light = 2130837648;
|
||||
public const int ic_audiotrack_light = 2130837648;
|
||||
|
||||
// aapt resource value: 0x7f020091
|
||||
public const int ic_cast_grey = 2130837649;
|
||||
public const int ic_bluetooth_grey = 2130837649;
|
||||
|
||||
// aapt resource value: 0x7f020092
|
||||
public const int ic_cast_light = 2130837650;
|
||||
public const int ic_bluetooth_white = 2130837650;
|
||||
|
||||
// aapt resource value: 0x7f020093
|
||||
public const int ic_cast_off_light = 2130837651;
|
||||
public const int ic_cast_dark = 2130837651;
|
||||
|
||||
// aapt resource value: 0x7f020094
|
||||
public const int ic_cast_on_0_light = 2130837652;
|
||||
public const int ic_cast_disabled_light = 2130837652;
|
||||
|
||||
// aapt resource value: 0x7f020095
|
||||
public const int ic_cast_on_1_light = 2130837653;
|
||||
public const int ic_cast_grey = 2130837653;
|
||||
|
||||
// aapt resource value: 0x7f020096
|
||||
public const int ic_cast_on_2_light = 2130837654;
|
||||
public const int ic_cast_light = 2130837654;
|
||||
|
||||
// aapt resource value: 0x7f020097
|
||||
public const int ic_cast_on_light = 2130837655;
|
||||
public const int ic_cast_off_light = 2130837655;
|
||||
|
||||
// aapt resource value: 0x7f020098
|
||||
public const int ic_cast_white = 2130837656;
|
||||
public const int ic_cast_on_0_light = 2130837656;
|
||||
|
||||
// aapt resource value: 0x7f020099
|
||||
public const int ic_close_dark = 2130837657;
|
||||
public const int ic_cast_on_1_light = 2130837657;
|
||||
|
||||
// aapt resource value: 0x7f02009a
|
||||
public const int ic_close_light = 2130837658;
|
||||
public const int ic_cast_on_2_light = 2130837658;
|
||||
|
||||
// aapt resource value: 0x7f02009b
|
||||
public const int ic_collapse = 2130837659;
|
||||
public const int ic_cast_on_light = 2130837659;
|
||||
|
||||
// aapt resource value: 0x7f02009c
|
||||
public const int ic_collapse_00000 = 2130837660;
|
||||
public const int ic_cast_white = 2130837660;
|
||||
|
||||
// aapt resource value: 0x7f02009d
|
||||
public const int ic_collapse_00001 = 2130837661;
|
||||
public const int ic_close_dark = 2130837661;
|
||||
|
||||
// aapt resource value: 0x7f02009e
|
||||
public const int ic_collapse_00002 = 2130837662;
|
||||
public const int ic_close_light = 2130837662;
|
||||
|
||||
// aapt resource value: 0x7f02009f
|
||||
public const int ic_collapse_00003 = 2130837663;
|
||||
public const int ic_collapse = 2130837663;
|
||||
|
||||
// aapt resource value: 0x7f0200a0
|
||||
public const int ic_collapse_00004 = 2130837664;
|
||||
public const int ic_collapse_00000 = 2130837664;
|
||||
|
||||
// aapt resource value: 0x7f0200a1
|
||||
public const int ic_collapse_00005 = 2130837665;
|
||||
public const int ic_collapse_00001 = 2130837665;
|
||||
|
||||
// aapt resource value: 0x7f0200a2
|
||||
public const int ic_collapse_00006 = 2130837666;
|
||||
public const int ic_collapse_00002 = 2130837666;
|
||||
|
||||
// aapt resource value: 0x7f0200a3
|
||||
public const int ic_collapse_00007 = 2130837667;
|
||||
public const int ic_collapse_00003 = 2130837667;
|
||||
|
||||
// aapt resource value: 0x7f0200a4
|
||||
public const int ic_collapse_00008 = 2130837668;
|
||||
public const int ic_collapse_00004 = 2130837668;
|
||||
|
||||
// aapt resource value: 0x7f0200a5
|
||||
public const int ic_collapse_00009 = 2130837669;
|
||||
public const int ic_collapse_00005 = 2130837669;
|
||||
|
||||
// aapt resource value: 0x7f0200a6
|
||||
public const int ic_collapse_00010 = 2130837670;
|
||||
public const int ic_collapse_00006 = 2130837670;
|
||||
|
||||
// aapt resource value: 0x7f0200a7
|
||||
public const int ic_collapse_00011 = 2130837671;
|
||||
public const int ic_collapse_00007 = 2130837671;
|
||||
|
||||
// aapt resource value: 0x7f0200a8
|
||||
public const int ic_collapse_00012 = 2130837672;
|
||||
public const int ic_collapse_00008 = 2130837672;
|
||||
|
||||
// aapt resource value: 0x7f0200a9
|
||||
public const int ic_collapse_00013 = 2130837673;
|
||||
public const int ic_collapse_00009 = 2130837673;
|
||||
|
||||
// aapt resource value: 0x7f0200aa
|
||||
public const int ic_collapse_00014 = 2130837674;
|
||||
public const int ic_collapse_00010 = 2130837674;
|
||||
|
||||
// aapt resource value: 0x7f0200ab
|
||||
public const int ic_collapse_00015 = 2130837675;
|
||||
public const int ic_collapse_00011 = 2130837675;
|
||||
|
||||
// aapt resource value: 0x7f0200ac
|
||||
public const int ic_errorstatus = 2130837676;
|
||||
public const int ic_collapse_00012 = 2130837676;
|
||||
|
||||
// aapt resource value: 0x7f0200ad
|
||||
public const int ic_expand = 2130837677;
|
||||
public const int ic_collapse_00013 = 2130837677;
|
||||
|
||||
// aapt resource value: 0x7f0200ae
|
||||
public const int ic_expand_00000 = 2130837678;
|
||||
public const int ic_collapse_00014 = 2130837678;
|
||||
|
||||
// aapt resource value: 0x7f0200af
|
||||
public const int ic_expand_00001 = 2130837679;
|
||||
public const int ic_collapse_00015 = 2130837679;
|
||||
|
||||
// aapt resource value: 0x7f0200b0
|
||||
public const int ic_expand_00002 = 2130837680;
|
||||
public const int ic_errorstatus = 2130837680;
|
||||
|
||||
// aapt resource value: 0x7f0200b1
|
||||
public const int ic_expand_00003 = 2130837681;
|
||||
public const int ic_expand = 2130837681;
|
||||
|
||||
// aapt resource value: 0x7f0200b2
|
||||
public const int ic_expand_00004 = 2130837682;
|
||||
public const int ic_expand_00000 = 2130837682;
|
||||
|
||||
// aapt resource value: 0x7f0200b3
|
||||
public const int ic_expand_00005 = 2130837683;
|
||||
public const int ic_expand_00001 = 2130837683;
|
||||
|
||||
// aapt resource value: 0x7f0200b4
|
||||
public const int ic_expand_00006 = 2130837684;
|
||||
public const int ic_expand_00002 = 2130837684;
|
||||
|
||||
// aapt resource value: 0x7f0200b5
|
||||
public const int ic_expand_00007 = 2130837685;
|
||||
public const int ic_expand_00003 = 2130837685;
|
||||
|
||||
// aapt resource value: 0x7f0200b6
|
||||
public const int ic_expand_00008 = 2130837686;
|
||||
public const int ic_expand_00004 = 2130837686;
|
||||
|
||||
// aapt resource value: 0x7f0200b7
|
||||
public const int ic_expand_00009 = 2130837687;
|
||||
public const int ic_expand_00005 = 2130837687;
|
||||
|
||||
// aapt resource value: 0x7f0200b8
|
||||
public const int ic_expand_00010 = 2130837688;
|
||||
public const int ic_expand_00006 = 2130837688;
|
||||
|
||||
// aapt resource value: 0x7f0200b9
|
||||
public const int ic_expand_00011 = 2130837689;
|
||||
public const int ic_expand_00007 = 2130837689;
|
||||
|
||||
// aapt resource value: 0x7f0200ba
|
||||
public const int ic_expand_00012 = 2130837690;
|
||||
public const int ic_expand_00008 = 2130837690;
|
||||
|
||||
// aapt resource value: 0x7f0200bb
|
||||
public const int ic_expand_00013 = 2130837691;
|
||||
public const int ic_expand_00009 = 2130837691;
|
||||
|
||||
// aapt resource value: 0x7f0200bc
|
||||
public const int ic_expand_00014 = 2130837692;
|
||||
public const int ic_expand_00010 = 2130837692;
|
||||
|
||||
// aapt resource value: 0x7f0200bd
|
||||
public const int ic_expand_00015 = 2130837693;
|
||||
public const int ic_expand_00011 = 2130837693;
|
||||
|
||||
// aapt resource value: 0x7f0200be
|
||||
public const int ic_media_pause = 2130837694;
|
||||
public const int ic_expand_00012 = 2130837694;
|
||||
|
||||
// aapt resource value: 0x7f0200bf
|
||||
public const int ic_media_play = 2130837695;
|
||||
public const int ic_expand_00013 = 2130837695;
|
||||
|
||||
// aapt resource value: 0x7f0200c0
|
||||
public const int ic_media_route_disabled_mono_dark = 2130837696;
|
||||
public const int ic_expand_00014 = 2130837696;
|
||||
|
||||
// aapt resource value: 0x7f0200c1
|
||||
public const int ic_media_route_off_mono_dark = 2130837697;
|
||||
public const int ic_expand_00015 = 2130837697;
|
||||
|
||||
// aapt resource value: 0x7f0200c2
|
||||
public const int ic_media_route_on_0_mono_dark = 2130837698;
|
||||
public const int ic_media_pause = 2130837698;
|
||||
|
||||
// aapt resource value: 0x7f0200c3
|
||||
public const int ic_media_route_on_1_mono_dark = 2130837699;
|
||||
public const int ic_media_play = 2130837699;
|
||||
|
||||
// aapt resource value: 0x7f0200c4
|
||||
public const int ic_media_route_on_2_mono_dark = 2130837700;
|
||||
public const int ic_media_route_disabled_mono_dark = 2130837700;
|
||||
|
||||
// aapt resource value: 0x7f0200c5
|
||||
public const int ic_media_route_on_mono_dark = 2130837701;
|
||||
public const int ic_media_route_off_mono_dark = 2130837701;
|
||||
|
||||
// aapt resource value: 0x7f0200c6
|
||||
public const int ic_pause_dark = 2130837702;
|
||||
public const int ic_media_route_on_0_mono_dark = 2130837702;
|
||||
|
||||
// aapt resource value: 0x7f0200c7
|
||||
public const int ic_pause_light = 2130837703;
|
||||
public const int ic_media_route_on_1_mono_dark = 2130837703;
|
||||
|
||||
// aapt resource value: 0x7f0200c8
|
||||
public const int ic_play_dark = 2130837704;
|
||||
public const int ic_media_route_on_2_mono_dark = 2130837704;
|
||||
|
||||
// aapt resource value: 0x7f0200c9
|
||||
public const int ic_play_light = 2130837705;
|
||||
public const int ic_media_route_on_mono_dark = 2130837705;
|
||||
|
||||
// aapt resource value: 0x7f0200ca
|
||||
public const int ic_speaker_dark = 2130837706;
|
||||
public const int ic_pause_dark = 2130837706;
|
||||
|
||||
// aapt resource value: 0x7f0200cb
|
||||
public const int ic_speaker_group_dark = 2130837707;
|
||||
public const int ic_pause_light = 2130837707;
|
||||
|
||||
// aapt resource value: 0x7f0200cc
|
||||
public const int ic_speaker_group_light = 2130837708;
|
||||
public const int ic_play_dark = 2130837708;
|
||||
|
||||
// aapt resource value: 0x7f0200cd
|
||||
public const int ic_speaker_light = 2130837709;
|
||||
public const int ic_play_light = 2130837709;
|
||||
|
||||
// aapt resource value: 0x7f0200ce
|
||||
public const int ic_successstatus = 2130837710;
|
||||
public const int ic_speaker_dark = 2130837710;
|
||||
|
||||
// aapt resource value: 0x7f0200cf
|
||||
public const int ic_tv_dark = 2130837711;
|
||||
public const int ic_speaker_group_dark = 2130837711;
|
||||
|
||||
// aapt resource value: 0x7f0200d0
|
||||
public const int ic_tv_light = 2130837712;
|
||||
public const int ic_speaker_group_light = 2130837712;
|
||||
|
||||
// aapt resource value: 0x7f0200d1
|
||||
public const int icon = 2130837713;
|
||||
public const int ic_speaker_light = 2130837713;
|
||||
|
||||
// aapt resource value: 0x7f0200d2
|
||||
public const int ion_chevron_right = 2130837714;
|
||||
public const int ic_successstatus = 2130837714;
|
||||
|
||||
// aapt resource value: 0x7f0200d3
|
||||
public const int lightbulb = 2130837715;
|
||||
public const int ic_tv_dark = 2130837715;
|
||||
|
||||
// aapt resource value: 0x7f0200d4
|
||||
public const int list_selector = 2130837716;
|
||||
public const int ic_tv_light = 2130837716;
|
||||
|
||||
// aapt resource value: 0x7f0200d5
|
||||
public const int @lock = 2130837717;
|
||||
public const int icon = 2130837717;
|
||||
|
||||
// aapt resource value: 0x7f0200d6
|
||||
public const int logo = 2130837718;
|
||||
public const int id = 2130837718;
|
||||
|
||||
// aapt resource value: 0x7f0200d7
|
||||
public const int more = 2130837719;
|
||||
public const int ion_chevron_right = 2130837719;
|
||||
|
||||
// aapt resource value: 0x7f0200d8
|
||||
public const int mr_dialog_material_background_dark = 2130837720;
|
||||
public const int launch = 2130837720;
|
||||
|
||||
// aapt resource value: 0x7f0200d9
|
||||
public const int mr_dialog_material_background_light = 2130837721;
|
||||
public const int lightbulb = 2130837721;
|
||||
|
||||
// aapt resource value: 0x7f0200da
|
||||
public const int mr_ic_audiotrack_light = 2130837722;
|
||||
public const int list_selector = 2130837722;
|
||||
|
||||
// aapt resource value: 0x7f0200db
|
||||
public const int mr_ic_cast_dark = 2130837723;
|
||||
public const int @lock = 2130837723;
|
||||
|
||||
// aapt resource value: 0x7f0200dc
|
||||
public const int mr_ic_cast_light = 2130837724;
|
||||
public const int login = 2130837724;
|
||||
|
||||
// aapt resource value: 0x7f0200dd
|
||||
public const int mr_ic_close_dark = 2130837725;
|
||||
public const int logo = 2130837725;
|
||||
|
||||
// aapt resource value: 0x7f0200de
|
||||
public const int mr_ic_close_light = 2130837726;
|
||||
public const int more = 2130837726;
|
||||
|
||||
// aapt resource value: 0x7f0200df
|
||||
public const int mr_ic_media_route_connecting_mono_dark = 2130837727;
|
||||
public const int mr_dialog_material_background_dark = 2130837727;
|
||||
|
||||
// aapt resource value: 0x7f0200e0
|
||||
public const int mr_ic_media_route_connecting_mono_light = 2130837728;
|
||||
public const int mr_dialog_material_background_light = 2130837728;
|
||||
|
||||
// aapt resource value: 0x7f0200e1
|
||||
public const int mr_ic_media_route_mono_dark = 2130837729;
|
||||
public const int mr_ic_audiotrack_light = 2130837729;
|
||||
|
||||
// aapt resource value: 0x7f0200e2
|
||||
public const int mr_ic_media_route_mono_light = 2130837730;
|
||||
public const int mr_ic_cast_dark = 2130837730;
|
||||
|
||||
// aapt resource value: 0x7f0200e3
|
||||
public const int mr_ic_pause_dark = 2130837731;
|
||||
public const int mr_ic_cast_light = 2130837731;
|
||||
|
||||
// aapt resource value: 0x7f0200e4
|
||||
public const int mr_ic_pause_light = 2130837732;
|
||||
public const int mr_ic_close_dark = 2130837732;
|
||||
|
||||
// aapt resource value: 0x7f0200e5
|
||||
public const int mr_ic_play_dark = 2130837733;
|
||||
public const int mr_ic_close_light = 2130837733;
|
||||
|
||||
// aapt resource value: 0x7f0200e6
|
||||
public const int mr_ic_play_light = 2130837734;
|
||||
public const int mr_ic_media_route_connecting_mono_dark = 2130837734;
|
||||
|
||||
// aapt resource value: 0x7f0200e7
|
||||
public const int notification_sm = 2130837735;
|
||||
|
||||
// aapt resource value: 0x7f0200fa
|
||||
public const int notification_template_icon_bg = 2130837754;
|
||||
public const int mr_ic_media_route_connecting_mono_light = 2130837735;
|
||||
|
||||
// aapt resource value: 0x7f0200e8
|
||||
public const int paperclip = 2130837736;
|
||||
public const int mr_ic_media_route_mono_dark = 2130837736;
|
||||
|
||||
// aapt resource value: 0x7f0200e9
|
||||
public const int plus = 2130837737;
|
||||
public const int mr_ic_media_route_mono_light = 2130837737;
|
||||
|
||||
// aapt resource value: 0x7f0200ea
|
||||
public const int refresh = 2130837738;
|
||||
public const int mr_ic_pause_dark = 2130837738;
|
||||
|
||||
// aapt resource value: 0x7f0200eb
|
||||
public const int roundedbg = 2130837739;
|
||||
public const int mr_ic_pause_light = 2130837739;
|
||||
|
||||
// aapt resource value: 0x7f0200ec
|
||||
public const int roundedbgdark = 2130837740;
|
||||
public const int mr_ic_play_dark = 2130837740;
|
||||
|
||||
// aapt resource value: 0x7f0200ed
|
||||
public const int search = 2130837741;
|
||||
public const int mr_ic_play_light = 2130837741;
|
||||
|
||||
// aapt resource value: 0x7f0200ee
|
||||
public const int share = 2130837742;
|
||||
public const int note = 2130837742;
|
||||
|
||||
// aapt resource value: 0x7f0200ef
|
||||
public const int share_tools = 2130837743;
|
||||
public const int notification_sm = 2130837743;
|
||||
|
||||
// aapt resource value: 0x7f020102
|
||||
public const int notification_template_icon_bg = 2130837762;
|
||||
|
||||
// aapt resource value: 0x7f0200f0
|
||||
public const int shield = 2130837744;
|
||||
public const int paperclip = 2130837744;
|
||||
|
||||
// aapt resource value: 0x7f0200f1
|
||||
public const int splash_screen = 2130837745;
|
||||
public const int plus = 2130837745;
|
||||
|
||||
// aapt resource value: 0x7f0200f2
|
||||
public const int star = 2130837746;
|
||||
public const int refresh = 2130837746;
|
||||
|
||||
// aapt resource value: 0x7f0200f3
|
||||
public const int star_selected = 2130837747;
|
||||
public const int roundedbg = 2130837747;
|
||||
|
||||
// aapt resource value: 0x7f0200f4
|
||||
public const int tools = 2130837748;
|
||||
public const int roundedbgdark = 2130837748;
|
||||
|
||||
// aapt resource value: 0x7f0200f5
|
||||
public const int tools_selected = 2130837749;
|
||||
public const int search = 2130837749;
|
||||
|
||||
// aapt resource value: 0x7f0200f6
|
||||
public const int trash = 2130837750;
|
||||
public const int share = 2130837750;
|
||||
|
||||
// aapt resource value: 0x7f0200f7
|
||||
public const int upload = 2130837751;
|
||||
public const int share_tools = 2130837751;
|
||||
|
||||
// aapt resource value: 0x7f0200f8
|
||||
public const int user = 2130837752;
|
||||
public const int shield = 2130837752;
|
||||
|
||||
// aapt resource value: 0x7f0200f9
|
||||
public const int yubikey = 2130837753;
|
||||
public const int splash_screen = 2130837753;
|
||||
|
||||
// aapt resource value: 0x7f0200fa
|
||||
public const int star = 2130837754;
|
||||
|
||||
// aapt resource value: 0x7f0200fb
|
||||
public const int star_selected = 2130837755;
|
||||
|
||||
// aapt resource value: 0x7f0200fc
|
||||
public const int tools = 2130837756;
|
||||
|
||||
// aapt resource value: 0x7f0200fd
|
||||
public const int tools_selected = 2130837757;
|
||||
|
||||
// aapt resource value: 0x7f0200fe
|
||||
public const int trash = 2130837758;
|
||||
|
||||
// aapt resource value: 0x7f0200ff
|
||||
public const int upload = 2130837759;
|
||||
|
||||
// aapt resource value: 0x7f020100
|
||||
public const int user = 2130837760;
|
||||
|
||||
// aapt resource value: 0x7f020101
|
||||
public const int yubikey = 2130837761;
|
||||
|
||||
static Drawable()
|
||||
{
|
||||
|
||||
BIN
src/Android/Resources/drawable-hdpi/android.png
Normal file
|
After Width: | Height: | Size: 530 B |
BIN
src/Android/Resources/drawable-hdpi/apple.png
Normal file
|
After Width: | Height: | Size: 625 B |
BIN
src/Android/Resources/drawable-hdpi/card.png
Normal file
|
After Width: | Height: | Size: 180 B |
BIN
src/Android/Resources/drawable-hdpi/clipboard.png
Normal file
|
After Width: | Height: | Size: 426 B |
|
Before Width: | Height: | Size: 434 B After Width: | Height: | Size: 431 B |
BIN
src/Android/Resources/drawable-hdpi/id.png
Normal file
|
After Width: | Height: | Size: 487 B |
BIN
src/Android/Resources/drawable-hdpi/launch.png
Normal file
|
After Width: | Height: | Size: 686 B |
BIN
src/Android/Resources/drawable-hdpi/login.png
Normal file
|
After Width: | Height: | Size: 904 B |
|
Before Width: | Height: | Size: 412 B After Width: | Height: | Size: 218 B |
BIN
src/Android/Resources/drawable-hdpi/note.png
Normal file
|
After Width: | Height: | Size: 344 B |
BIN
src/Android/Resources/drawable-xhdpi/android.png
Normal file
|
After Width: | Height: | Size: 659 B |
BIN
src/Android/Resources/drawable-xhdpi/apple.png
Normal file
|
After Width: | Height: | Size: 741 B |
BIN
src/Android/Resources/drawable-xhdpi/card.png
Normal file
|
After Width: | Height: | Size: 326 B |
BIN
src/Android/Resources/drawable-xhdpi/clipboard.png
Normal file
|
After Width: | Height: | Size: 487 B |
|
Before Width: | Height: | Size: 563 B After Width: | Height: | Size: 598 B |
BIN
src/Android/Resources/drawable-xhdpi/id.png
Normal file
|
After Width: | Height: | Size: 545 B |
BIN
src/Android/Resources/drawable-xhdpi/launch.png
Normal file
|
After Width: | Height: | Size: 910 B |
BIN
src/Android/Resources/drawable-xhdpi/login.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 567 B After Width: | Height: | Size: 284 B |
BIN
src/Android/Resources/drawable-xhdpi/note.png
Normal file
|
After Width: | Height: | Size: 382 B |
BIN
src/Android/Resources/drawable-xxhdpi/android.png
Normal file
|
After Width: | Height: | Size: 994 B |
BIN
src/Android/Resources/drawable-xxhdpi/apple.png
Normal file
|
After Width: | Height: | Size: 1005 B |
BIN
src/Android/Resources/drawable-xxhdpi/card.png
Normal file
|
After Width: | Height: | Size: 234 B |
BIN
src/Android/Resources/drawable-xxhdpi/clipboard.png
Normal file
|
After Width: | Height: | Size: 677 B |
|
Before Width: | Height: | Size: 734 B After Width: | Height: | Size: 810 B |
BIN
src/Android/Resources/drawable-xxhdpi/id.png
Normal file
|
After Width: | Height: | Size: 868 B |
BIN
src/Android/Resources/drawable-xxhdpi/launch.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/Android/Resources/drawable-xxhdpi/login.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 732 B After Width: | Height: | Size: 400 B |
BIN
src/Android/Resources/drawable-xxhdpi/note.png
Normal file
|
After Width: | Height: | Size: 359 B |
BIN
src/Android/Resources/drawable-xxxhdpi/android.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/Android/Resources/drawable-xxxhdpi/apple.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/Android/Resources/drawable-xxxhdpi/card.png
Normal file
|
After Width: | Height: | Size: 469 B |
BIN
src/Android/Resources/drawable-xxxhdpi/clipboard.png
Normal file
|
After Width: | Height: | Size: 737 B |
|
Before Width: | Height: | Size: 889 B After Width: | Height: | Size: 1009 B |
BIN
src/Android/Resources/drawable-xxxhdpi/id.png
Normal file
|
After Width: | Height: | Size: 807 B |
BIN
src/Android/Resources/drawable-xxxhdpi/launch.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/Android/Resources/drawable-xxxhdpi/login.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 921 B After Width: | Height: | Size: 488 B |
BIN
src/Android/Resources/drawable-xxxhdpi/note.png
Normal file
|
After Width: | Height: | Size: 524 B |
BIN
src/Android/Resources/drawable/android.png
Normal file
|
After Width: | Height: | Size: 406 B |
BIN
src/Android/Resources/drawable/apple.png
Normal file
|
After Width: | Height: | Size: 446 B |
BIN
src/Android/Resources/drawable/card.png
Normal file
|
After Width: | Height: | Size: 229 B |
BIN
src/Android/Resources/drawable/clipboard.png
Normal file
|
After Width: | Height: | Size: 350 B |
|
Before Width: | Height: | Size: 346 B After Width: | Height: | Size: 388 B |
BIN
src/Android/Resources/drawable/id.png
Normal file
|
After Width: | Height: | Size: 342 B |
BIN
src/Android/Resources/drawable/launch.png
Normal file
|
After Width: | Height: | Size: 596 B |
BIN
src/Android/Resources/drawable/login.png
Normal file
|
After Width: | Height: | Size: 657 B |
|
Before Width: | Height: | Size: 288 B After Width: | Height: | Size: 165 B |
BIN
src/Android/Resources/drawable/note.png
Normal file
|
After Width: | Height: | Size: 272 B |
560
src/Android/Services/AndroidPushNotificationService.cs
Normal file
@@ -0,0 +1,560 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Utilities;
|
||||
using System.Threading;
|
||||
using Xamarin.Forms;
|
||||
using Android.Gms.Gcm.Iid;
|
||||
using Android.Gms.Gcm;
|
||||
using Java.IO;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Android.Support.V4.App;
|
||||
using Android.Media;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Bit.Android.Services
|
||||
{
|
||||
public class AndroidPushNotificationService : IPushNotificationService
|
||||
{
|
||||
private const string GcmPreferencesKey = "GCMPreferences";
|
||||
private const string Tag = "PushNotification";
|
||||
|
||||
internal static IPushNotificationListener Listener { get; set; }
|
||||
public string Token => GetRegistrationId();
|
||||
|
||||
public void Register()
|
||||
{
|
||||
|
||||
System.Diagnostics.Debug.WriteLine(
|
||||
$"{PushNotificationContants.DomainName} - Register - Registering push notifications");
|
||||
|
||||
if(string.IsNullOrEmpty(CrossPushNotification.SenderId))
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(
|
||||
$"{PushNotificationContants.DomainName} - Register - SenderId is missing.");
|
||||
|
||||
CrossPushNotification.PushNotificationListener.OnError(
|
||||
$"{PushNotificationContants.DomainName} - Register - Sender Id is missing.", Device.Android);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(
|
||||
$"{PushNotificationContants.DomainName} - Register - Registering for Push Notifications");
|
||||
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Intent intent = new Intent(global::Android.App.Application.Context,
|
||||
typeof(PushNotificationRegistrationIntentService));
|
||||
|
||||
global::Android.App.Application.Context.StartService(intent);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"{Tag} - Error : {ex.Message}");
|
||||
CrossPushNotification.PushNotificationListener.OnError($"{Tag} - Register - {ex.Message}",
|
||||
Device.Android);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void Unregister()
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(
|
||||
$"{PushNotificationContants.DomainName} - Unregister - Unregistering push notifications");
|
||||
try
|
||||
{
|
||||
var instanceID = InstanceID.GetInstance(global::Android.App.Application.Context);
|
||||
instanceID.DeleteToken(CrossPushNotification.SenderId, GoogleCloudMessaging.InstanceIdScope);
|
||||
|
||||
CrossPushNotification.PushNotificationListener.OnUnregistered(Device.Android);
|
||||
StoreRegistrationId(global::Android.App.Application.Context, string.Empty);
|
||||
|
||||
}
|
||||
catch(IOException ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"{Tag} - Error : {ex.Message}");
|
||||
CrossPushNotification.PushNotificationListener.OnError(
|
||||
$"{Tag} - Unregister - {ex.Message}", Device.Android);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private string GetRegistrationId()
|
||||
{
|
||||
var context = global::Android.App.Application.Context;
|
||||
var prefs = GetGCMPreferences(context);
|
||||
var registrationId = prefs.GetString(PushNotificationContants.Token, string.Empty);
|
||||
if(string.IsNullOrEmpty(registrationId))
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"{PushNotificationContants.DomainName} - Registration not found.");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// Check if app was updated; if so, it must clear the registration ID
|
||||
// since the existing registration ID is not guaranteed to work with
|
||||
// the new app version.
|
||||
var registeredVersion = prefs.GetInt(PushNotificationContants.AppVersion, Java.Lang.Integer.MinValue);
|
||||
var currentVersion = GetAppVersion(context);
|
||||
if(registeredVersion != currentVersion)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"{PushNotificationContants.DomainName} - App version changed.");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return registrationId;
|
||||
}
|
||||
|
||||
internal static ISharedPreferences GetGCMPreferences(Context context)
|
||||
{
|
||||
return context.GetSharedPreferences(GcmPreferencesKey, FileCreationMode.Private);
|
||||
}
|
||||
|
||||
internal static int GetAppVersion(Context context)
|
||||
{
|
||||
try
|
||||
{
|
||||
var packageInfo = context.PackageManager.GetPackageInfo(context.PackageName, 0);
|
||||
return packageInfo.VersionCode;
|
||||
}
|
||||
catch(global::Android.Content.PM.PackageManager.NameNotFoundException e)
|
||||
{
|
||||
// should never happen
|
||||
throw new Java.Lang.RuntimeException("Could not get package name: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void StoreRegistrationId(Context context, string regId)
|
||||
{
|
||||
var prefs = GetGCMPreferences(context);
|
||||
var appVersion = GetAppVersion(context);
|
||||
|
||||
System.Diagnostics.Debug.WriteLine(
|
||||
$"{PushNotificationContants.DomainName} - Saving token on app version {appVersion}");
|
||||
|
||||
var editor = prefs.Edit();
|
||||
editor.PutString(PushNotificationContants.Token, regId);
|
||||
editor.PutInt(PushNotificationContants.AppVersion, appVersion);
|
||||
editor.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
[Service(Exported = false)]
|
||||
public class PushNotificationRegistrationIntentService : IntentService
|
||||
{
|
||||
private const string Tag = "PushNotificationRegistationIntentService";
|
||||
private string[] _topics = new string[] { "global" };
|
||||
private readonly object _syncLock = new object();
|
||||
|
||||
protected override void OnHandleIntent(Intent intent)
|
||||
{
|
||||
try
|
||||
{
|
||||
var extras = intent.Extras;
|
||||
lock(_syncLock)
|
||||
{
|
||||
var instanceID = InstanceID.GetInstance(global::Android.App.Application.Context);
|
||||
var token = instanceID.GetToken(CrossPushNotification.SenderId,
|
||||
GoogleCloudMessaging.InstanceIdScope, null);
|
||||
CrossPushNotification.PushNotificationListener.OnRegistered(token, Device.Android);
|
||||
AndroidPushNotificationService.StoreRegistrationId(global::Android.App.Application.Context, token);
|
||||
SubscribeTopics(token);
|
||||
System.Diagnostics.Debug.WriteLine($"{token} - Device registered, registration ID={Tag}");
|
||||
}
|
||||
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"{ex.Message} - Error : {Tag}");
|
||||
CrossPushNotification.PushNotificationListener.OnError(
|
||||
$"{ex.ToString()} - Register - {Tag}", Device.Android);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void SubscribeTopics(string token)
|
||||
{
|
||||
var pubSub = GcmPubSub.GetInstance(this);
|
||||
foreach(var topic in _topics)
|
||||
{
|
||||
pubSub.Subscribe(token, "/topics/" + topic, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Service(Exported = false)]
|
||||
[IntentFilter(new string[] { "com.google.android.gms.iid.InstanceID" })]
|
||||
public class PushNotificationInstanceIDListenerService : InstanceIDListenerService
|
||||
{
|
||||
private const string Tag = "PushNotificationInstanceIDLS";
|
||||
|
||||
public override void OnTokenRefresh()
|
||||
{
|
||||
base.OnTokenRefresh();
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var intent = new Intent(global::Android.App.Application.Context,
|
||||
typeof(PushNotificationRegistrationIntentService));
|
||||
global::Android.App.Application.Context.StartService(intent);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"{ex.Message} - Error : {Tag}");
|
||||
CrossPushNotification.PushNotificationListener.OnError(
|
||||
$"{ex.ToString()} - Register - {Tag}", Device.Android);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Service(Exported = false, Name = "pushnotification.plugin.PushNotificationGcmListener")]
|
||||
[IntentFilter(new string[] { "com.google.android.c2dm.intent.RECEIVE" },
|
||||
Categories = new string[] { "com.x8bit.bitwarden" })]
|
||||
public class PushNotificationGcmListener : GcmListenerService
|
||||
{
|
||||
public override void OnMessageReceived(string from, Bundle extras)
|
||||
{
|
||||
if(extras != null && !extras.IsEmpty)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(
|
||||
$"{PushNotificationContants.DomainName} - GCM Listener - Push Received");
|
||||
|
||||
var parameters = new Dictionary<string, object>();
|
||||
var values = new JObject();
|
||||
foreach(var key in extras.KeySet())
|
||||
{
|
||||
var value = extras.Get(key).ToString();
|
||||
|
||||
if(ValidateJSON(value))
|
||||
{
|
||||
values.Add(key, JObject.Parse(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
values.Add(key, value);
|
||||
}
|
||||
|
||||
parameters.Add(key, extras.Get(key));
|
||||
System.Diagnostics.Debug.WriteLine(
|
||||
$"{PushNotificationContants.DomainName} - GCM Listener - Push Params {key} : {extras.Get(key)}");
|
||||
}
|
||||
|
||||
var context = global::Android.App.Application.Context;
|
||||
CrossPushNotification.PushNotificationListener.OnMessage(values, Device.Android);
|
||||
|
||||
try
|
||||
{
|
||||
var notifyId = 0;
|
||||
var title = context.ApplicationInfo.LoadLabel(context.PackageManager);
|
||||
var message = string.Empty;
|
||||
var tag = string.Empty;
|
||||
|
||||
if(!string.IsNullOrEmpty(CrossPushNotification.NotificationContentTextKey) &&
|
||||
parameters.ContainsKey(CrossPushNotification.NotificationContentTextKey))
|
||||
{
|
||||
message = parameters[CrossPushNotification.NotificationContentTextKey].ToString();
|
||||
}
|
||||
else if(parameters.ContainsKey(PushNotificationContants.Alert))
|
||||
{
|
||||
message = parameters[PushNotificationContants.Alert].ToString();
|
||||
}
|
||||
else if(parameters.ContainsKey(PushNotificationContants.Message))
|
||||
{
|
||||
message = parameters[PushNotificationContants.Message].ToString();
|
||||
}
|
||||
else if(parameters.ContainsKey(PushNotificationContants.Subtitle))
|
||||
{
|
||||
message = parameters[PushNotificationContants.Subtitle].ToString();
|
||||
}
|
||||
else if(parameters.ContainsKey(PushNotificationContants.Text))
|
||||
{
|
||||
message = parameters[PushNotificationContants.Text].ToString();
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(CrossPushNotification.NotificationContentTitleKey) &&
|
||||
parameters.ContainsKey(CrossPushNotification.NotificationContentTitleKey))
|
||||
{
|
||||
title = parameters[CrossPushNotification.NotificationContentTitleKey].ToString();
|
||||
}
|
||||
else if(parameters.ContainsKey(PushNotificationContants.Title))
|
||||
{
|
||||
if(!string.IsNullOrEmpty(message))
|
||||
{
|
||||
title = parameters[PushNotificationContants.Title].ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
message = parameters[PushNotificationContants.Title].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
if(string.IsNullOrEmpty(message))
|
||||
{
|
||||
var data = (
|
||||
!string.IsNullOrEmpty(CrossPushNotification.NotificationContentDataKey) &&
|
||||
values[CrossPushNotification.NotificationContentDataKey] != null) ?
|
||||
values[CrossPushNotification.NotificationContentDataKey] :
|
||||
values[PushNotificationContants.Data];
|
||||
|
||||
if(data != null)
|
||||
{
|
||||
if(!string.IsNullOrEmpty(CrossPushNotification.NotificationContentTextKey) &&
|
||||
data[CrossPushNotification.NotificationContentTextKey] != null)
|
||||
{
|
||||
message = data[CrossPushNotification.NotificationContentTextKey].ToString();
|
||||
}
|
||||
else if(data[PushNotificationContants.Alert] != null)
|
||||
{
|
||||
message = data[PushNotificationContants.Alert].ToString();
|
||||
}
|
||||
else if(data[PushNotificationContants.Message] != null)
|
||||
{
|
||||
message = data[PushNotificationContants.Message].ToString();
|
||||
}
|
||||
else if(data[PushNotificationContants.Subtitle] != null)
|
||||
{
|
||||
message = data[PushNotificationContants.Subtitle].ToString();
|
||||
}
|
||||
else if(data[PushNotificationContants.Text] != null)
|
||||
{
|
||||
message = data[PushNotificationContants.Text].ToString();
|
||||
}
|
||||
|
||||
if(!string.IsNullOrEmpty(CrossPushNotification.NotificationContentTitleKey) &&
|
||||
data[CrossPushNotification.NotificationContentTitleKey] != null)
|
||||
{
|
||||
title = data[CrossPushNotification.NotificationContentTitleKey].ToString();
|
||||
}
|
||||
else if(data[PushNotificationContants.Title] != null)
|
||||
{
|
||||
if(!string.IsNullOrEmpty(message))
|
||||
{
|
||||
title = data[PushNotificationContants.Title].ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
message = data[PushNotificationContants.Title].ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(parameters.ContainsKey(PushNotificationContants.Id))
|
||||
{
|
||||
var str = parameters[PushNotificationContants.Id].ToString();
|
||||
try
|
||||
{
|
||||
notifyId = Convert.ToInt32(str);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
// Keep the default value of zero for the notify_id, but log the conversion problem.
|
||||
System.Diagnostics.Debug.WriteLine("Failed to convert {0} to an integer", str);
|
||||
}
|
||||
}
|
||||
|
||||
if(parameters.ContainsKey(PushNotificationContants.Tag))
|
||||
{
|
||||
tag = parameters[PushNotificationContants.Tag].ToString();
|
||||
}
|
||||
|
||||
if(!parameters.ContainsKey(PushNotificationContants.Silent) ||
|
||||
!System.Boolean.Parse(parameters[PushNotificationContants.Silent].ToString()))
|
||||
{
|
||||
if(CrossPushNotification.PushNotificationListener.ShouldShowNotification())
|
||||
{
|
||||
CreateNotification(title, message, notifyId, tag, extras);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch(Java.Lang.Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(ex.ToString());
|
||||
}
|
||||
catch(Exception ex1)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(ex1.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateNotification(string title, string message, int notifyId, string tag, Bundle extras)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(
|
||||
$"{PushNotificationContants.DomainName} - PushNotification - Message {title} : {message}");
|
||||
|
||||
NotificationCompat.Builder builder = null;
|
||||
var context = global::Android.App.Application.Context;
|
||||
|
||||
if(CrossPushNotification.SoundUri == null)
|
||||
{
|
||||
CrossPushNotification.SoundUri = RingtoneManager.GetDefaultUri(RingtoneType.Notification);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(CrossPushNotification.IconResource == 0)
|
||||
{
|
||||
CrossPushNotification.IconResource = context.ApplicationInfo.Icon;
|
||||
}
|
||||
else
|
||||
{
|
||||
var name = context.Resources.GetResourceName(CrossPushNotification.IconResource);
|
||||
if(name == null)
|
||||
{
|
||||
CrossPushNotification.IconResource = context.ApplicationInfo.Icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(global::Android.Content.Res.Resources.NotFoundException ex)
|
||||
{
|
||||
CrossPushNotification.IconResource = context.ApplicationInfo.Icon;
|
||||
System.Diagnostics.Debug.WriteLine(ex.ToString());
|
||||
}
|
||||
|
||||
var resultIntent = context.PackageManager.GetLaunchIntentForPackage(context.PackageName);
|
||||
if(extras != null)
|
||||
{
|
||||
resultIntent.PutExtras(extras);
|
||||
}
|
||||
|
||||
// Create a PendingIntent; we're only using one PendingIntent (ID = 0):
|
||||
const int pendingIntentId = 0;
|
||||
var resultPendingIntent = PendingIntent.GetActivity(context, pendingIntentId,
|
||||
resultIntent, PendingIntentFlags.OneShot);
|
||||
|
||||
// Build the notification
|
||||
builder = new NotificationCompat.Builder(context)
|
||||
.SetAutoCancel(true) // dismiss the notification from the notification area when the user clicks on it
|
||||
.SetContentIntent(resultPendingIntent) // start up this activity when the user clicks the intent.
|
||||
.SetContentTitle(title) // Set the title
|
||||
.SetSound(CrossPushNotification.SoundUri)
|
||||
.SetSmallIcon(CrossPushNotification.IconResource) // This is the icon to display
|
||||
.SetContentText(message); // the message to display.
|
||||
|
||||
if(Build.VERSION.SdkInt >= BuildVersionCodes.JellyBean)
|
||||
{
|
||||
// Using BigText notification style to support long message
|
||||
var style = new NotificationCompat.BigTextStyle();
|
||||
style.BigText(message);
|
||||
builder.SetStyle(style);
|
||||
}
|
||||
|
||||
var notificationManager = (NotificationManager)context.GetSystemService(NotificationService);
|
||||
notificationManager.Notify(tag, notifyId, builder.Build());
|
||||
}
|
||||
|
||||
private static bool ValidateJSON(string s)
|
||||
{
|
||||
try
|
||||
{
|
||||
JObject.Parse(s);
|
||||
return true;
|
||||
}
|
||||
catch(JsonReaderException ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(ex.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[BroadcastReceiver(Exported = true, Permission = "com.google.android.c2dm.permission.SEND")]
|
||||
[IntentFilter(new string[] { "com.google.android.c2dm.intent.RECEIVE" },
|
||||
Categories = new string[] { "com.x8bit.bitwarden" })]
|
||||
public class PushNotificationsReceiver : GcmReceiver
|
||||
{ }
|
||||
|
||||
[Service]
|
||||
public class AndroidPushService : Service
|
||||
{
|
||||
public override void OnCreate()
|
||||
{
|
||||
base.OnCreate();
|
||||
System.Diagnostics.Debug.WriteLine("Push Notification Service - Created");
|
||||
}
|
||||
|
||||
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Push Notification Service - Started");
|
||||
return StartCommandResult.Sticky;
|
||||
}
|
||||
|
||||
public override IBinder OnBind(Intent intent)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Push Notification Service - Binded");
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void OnDestroy()
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("Push Notification Service - Destroyed");
|
||||
base.OnDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
internal class CrossPushNotification
|
||||
{
|
||||
private static Lazy<IPushNotificationService> Implementation = new Lazy<IPushNotificationService>(
|
||||
() => new AndroidPushNotificationService(),
|
||||
LazyThreadSafetyMode.PublicationOnly);
|
||||
public static bool IsInitialized => PushNotificationListener != null;
|
||||
public static IPushNotificationListener PushNotificationListener { get; private set; }
|
||||
|
||||
public static string SenderId { get; set; }
|
||||
public static string NotificationContentTitleKey { get; set; }
|
||||
public static string NotificationContentTextKey { get; set; }
|
||||
public static string NotificationContentDataKey { get; set; }
|
||||
public static int IconResource { get; set; }
|
||||
public static global::Android.Net.Uri SoundUri { get; set; }
|
||||
|
||||
public static void Initialize<T>(T listener, string senderId) where T : IPushNotificationListener
|
||||
{
|
||||
SenderId = senderId;
|
||||
|
||||
if(PushNotificationListener == null)
|
||||
{
|
||||
PushNotificationListener = listener;
|
||||
System.Diagnostics.Debug.WriteLine("PushNotification plugin initialized.");
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("PushNotification plugin already initialized.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void Initialize<T>(string senderId) where T : IPushNotificationListener, new()
|
||||
{
|
||||
Initialize(new T(), senderId);
|
||||
}
|
||||
|
||||
public static IPushNotificationService Current
|
||||
{
|
||||
get
|
||||
{
|
||||
if(!IsInitialized)
|
||||
{
|
||||
throw new Exception("Not initialized.");
|
||||
}
|
||||
|
||||
var ret = Implementation.Value;
|
||||
if(ret == null)
|
||||
{
|
||||
throw new Exception("Not in PCL");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
<package id="Plugin.Fingerprint" version="1.4.5" targetFramework="monoandroid71" />
|
||||
<package id="SimpleInjector" version="4.0.8" targetFramework="monoandroid71" />
|
||||
<package id="Splat" version="1.6.2" targetFramework="monoandroid60" />
|
||||
<package id="sqlite-net-pcl" version="1.4.118" targetFramework="monoandroid71" />
|
||||
<package id="sqlite-net-pcl" version="1.5.166-beta" targetFramework="monoandroid71" />
|
||||
<package id="SQLitePCLRaw.bundle_green" version="1.1.8" targetFramework="monoandroid71" />
|
||||
<package id="SQLitePCLRaw.core" version="1.1.8" targetFramework="monoandroid71" />
|
||||
<package id="SQLitePCLRaw.lib.e_sqlite3.android" version="1.1.8" targetFramework="monoandroid71" />
|
||||
@@ -69,7 +69,6 @@
|
||||
<package id="System.Xml.XDocument" version="4.0.11" targetFramework="monoandroid71" />
|
||||
<package id="Validation" version="2.3.7" targetFramework="monoandroid60" />
|
||||
<package id="Xam.Plugin.Connectivity" version="3.0.2" targetFramework="monoandroid71" />
|
||||
<package id="Xam.Plugin.PushNotification" version="1.2.4" targetFramework="monoandroid60" developmentDependency="true" />
|
||||
<package id="Xam.Plugins.Settings" version="3.0.1" targetFramework="monoandroid71" />
|
||||
<package id="Xamarin.Android.Support.Animated.Vector.Drawable" version="23.3.0" targetFramework="monoandroid60" />
|
||||
<package id="Xamarin.Android.Support.Design" version="23.3.0" targetFramework="monoandroid60" />
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IAttachmentRepository : IRepository<AttachmentData, string>
|
||||
{
|
||||
Task<IEnumerable<AttachmentData>> GetAllByLoginIdAsync(string loginId);
|
||||
Task<IEnumerable<AttachmentData>> GetAllByCipherIdAsync(string cipherId);
|
||||
Task<IEnumerable<AttachmentData>> GetAllByUserIdAsync(string userId);
|
||||
}
|
||||
}
|
||||
|
||||
13
src/App/Abstractions/Repositories/ICipherRepository.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Data;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ICipherRepository : IRepository<CipherData, string>
|
||||
{
|
||||
Task<IEnumerable<CipherData>> GetAllByUserIdAsync(string userId);
|
||||
Task<IEnumerable<CipherData>> GetAllByUserIdAsync(string userId, bool favorite);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,6 @@ namespace Bit.App.Abstractions
|
||||
public interface IFolderRepository : IRepository<FolderData, string>
|
||||
{
|
||||
Task<IEnumerable<FolderData>> GetAllByUserIdAsync(string userId);
|
||||
Task DeleteWithLoginUpdateAsync(string id, DateTime revisionDate);
|
||||
Task DeleteWithCipherUpdateAsync(string id, DateTime revisionDate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Data;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ILoginRepository : IRepository<LoginData, string>
|
||||
{
|
||||
Task<IEnumerable<LoginData>> GetAllByUserIdAsync(string userId);
|
||||
Task<IEnumerable<LoginData>> GetAllByUserIdAsync(string userId, bool favorite);
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,12 @@ namespace Bit.App.Abstractions
|
||||
DateTime LastCacheClear { get; set; }
|
||||
bool AutofillPersistNotification { get; set; }
|
||||
bool AutofillPasswordField { get; set; }
|
||||
bool DisableWebsiteIcons { get; set; }
|
||||
string SecurityStamp { get; set; }
|
||||
string BaseUrl { get; set; }
|
||||
string WebVaultUrl { get; set; }
|
||||
string ApiUrl { get; set; }
|
||||
string IdentityUrl { get; set; }
|
||||
string IconsUrl { get; set; }
|
||||
}
|
||||
}
|
||||
21
src/App/Abstractions/Services/ICipherService.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models;
|
||||
using Bit.App.Models.Api;
|
||||
using System;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ICipherService
|
||||
{
|
||||
Task<Cipher> GetByIdAsync(string id);
|
||||
Task<IEnumerable<Cipher>> GetAllAsync();
|
||||
Task<IEnumerable<Cipher>> GetAllAsync(bool favorites);
|
||||
Task<Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>>> GetAllAsync(string uriString);
|
||||
Task<ApiResult<CipherResponse>> SaveAsync(Cipher cipher);
|
||||
Task<ApiResult> DeleteAsync(string id);
|
||||
Task<byte[]> DownloadAndDecryptAttachmentAsync(string url, string orgId = null);
|
||||
Task<ApiResult<CipherResponse>> EncryptAndSaveAttachmentAsync(Cipher cipher, byte[] data, string fileName);
|
||||
Task<ApiResult> DeleteAttachmentAsync(Cipher cipher, string attachmentId);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models;
|
||||
using Bit.App.Models.Api;
|
||||
using System;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface ILoginService
|
||||
{
|
||||
Task<Login> GetByIdAsync(string id);
|
||||
Task<IEnumerable<Login>> GetAllAsync();
|
||||
Task<IEnumerable<Login>> GetAllAsync(bool favorites);
|
||||
Task<Tuple<IEnumerable<Login>, IEnumerable<Login>>> GetAllAsync(string uriString);
|
||||
Task<ApiResult<CipherResponse>> SaveAsync(Login login);
|
||||
Task<ApiResult> DeleteAsync(string id);
|
||||
Task<byte[]> DownloadAndDecryptAttachmentAsync(string url, string orgId = null);
|
||||
Task<ApiResult<CipherResponse>> EncryptAndSaveAttachmentAsync(Login login, byte[] data, string fileName);
|
||||
Task<ApiResult> DeleteAttachmentAsync(Login login, string attachmentId);
|
||||
}
|
||||
}
|
||||
9
src/App/Abstractions/Services/IPushNotification.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IPushNotificationService
|
||||
{
|
||||
string Token { get; }
|
||||
void Register();
|
||||
void Unregister();
|
||||
}
|
||||
}
|
||||
13
src/App/Abstractions/Services/IPushNotificationListener.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Bit.App.Abstractions
|
||||
{
|
||||
public interface IPushNotificationListener
|
||||
{
|
||||
void OnMessage(JObject values, string device);
|
||||
void OnRegistered(string token, string device);
|
||||
void OnUnregistered(string device);
|
||||
void OnError(string message, string device);
|
||||
bool ShouldShowNotification();
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace Bit.App.Abstractions
|
||||
Task<bool> SyncCipherAsync(string id);
|
||||
Task<bool> SyncFolderAsync(string id);
|
||||
Task<bool> SyncDeleteFolderAsync(string id, DateTime revisionDate);
|
||||
Task<bool> SyncDeleteLoginAsync(string id);
|
||||
Task<bool> SyncDeleteCipherAsync(string id);
|
||||
Task<bool> SyncSettingsAsync();
|
||||
Task<bool> SyncProfileAsync();
|
||||
Task<bool> FullSyncAsync(bool forceSync = false);
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Bit.App
|
||||
|
||||
if(authService.IsAuthenticated && _uri != null)
|
||||
{
|
||||
MainPage = new ExtendedNavigationPage(new VaultAutofillListLoginsPage(_uri));
|
||||
MainPage = new ExtendedNavigationPage(new VaultAutofillListCiphersPage(_uri));
|
||||
}
|
||||
else if(authService.IsAuthenticated)
|
||||
{
|
||||
@@ -103,7 +103,7 @@ namespace Bit.App
|
||||
|
||||
if(string.IsNullOrWhiteSpace(_uri))
|
||||
{
|
||||
Helpers.PerformUpdateTasks(_settings, _appInfoService, _databaseService);
|
||||
Helpers.PerformUpdateTasks(_settings, _appInfoService, _databaseService, _syncService);
|
||||
await Task.Run(() => FullSyncAsync()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
<Compile Include="Abstractions\Repositories\ISettingsRepository.cs" />
|
||||
<Compile Include="Abstractions\Services\IAppSettingsService.cs" />
|
||||
<Compile Include="Abstractions\Services\IMemoryService.cs" />
|
||||
<Compile Include="Abstractions\Services\IPushNotificationListener.cs" />
|
||||
<Compile Include="Abstractions\Services\IPushNotification.cs" />
|
||||
<Compile Include="Abstractions\Services\ISettingsService.cs" />
|
||||
<Compile Include="Abstractions\Services\ITokenService.cs" />
|
||||
<Compile Include="Abstractions\Services\IHttpService.cs" />
|
||||
@@ -56,7 +58,7 @@
|
||||
<Compile Include="Abstractions\Services\IKeyDerivationService.cs" />
|
||||
<Compile Include="Abstractions\Services\ILogService.cs" />
|
||||
<Compile Include="Abstractions\Services\IReflectionService.cs" />
|
||||
<Compile Include="Abstractions\Services\ILoginService.cs" />
|
||||
<Compile Include="Abstractions\Services\ICipherService.cs" />
|
||||
<Compile Include="Abstractions\Services\IFolderService.cs" />
|
||||
<Compile Include="App.cs" />
|
||||
<Compile Include="Abstractions\Services\ISecureStorageService.cs" />
|
||||
@@ -87,7 +89,9 @@
|
||||
<Compile Include="Controls\PinControl.cs" />
|
||||
<Compile Include="Controls\VaultAttachmentsViewCell.cs" />
|
||||
<Compile Include="Controls\VaultListViewCell.cs" />
|
||||
<Compile Include="Enums\DeviceType.cs" />
|
||||
<Compile Include="Enums\FieldType.cs" />
|
||||
<Compile Include="Enums\SecureNoteType.cs" />
|
||||
<Compile Include="Enums\TwoFactorProviderType.cs" />
|
||||
<Compile Include="Enums\EncryptionType.cs" />
|
||||
<Compile Include="Enums\OrganizationUserType.cs" />
|
||||
@@ -101,6 +105,9 @@
|
||||
<Compile Include="Models\Api\ApiResult.cs" />
|
||||
<Compile Include="Models\Api\CipherDataModel.cs" />
|
||||
<Compile Include="Models\Api\FieldDataModel.cs" />
|
||||
<Compile Include="Models\Api\CardDataModel.cs" />
|
||||
<Compile Include="Models\Api\IdentityDataModel.cs" />
|
||||
<Compile Include="Models\Api\SecureNoteDataModel.cs" />
|
||||
<Compile Include="Models\Api\Request\DeviceTokenRequest.cs" />
|
||||
<Compile Include="Models\Api\Request\FolderRequest.cs" />
|
||||
<Compile Include="Models\Api\Request\DeviceRequest.cs" />
|
||||
@@ -122,16 +129,20 @@
|
||||
<Compile Include="Models\Api\Response\TokenResponse.cs" />
|
||||
<Compile Include="Models\Api\Response\ProfileResponse.cs" />
|
||||
<Compile Include="Models\Api\LoginDataModel.cs" />
|
||||
<Compile Include="Models\Card.cs" />
|
||||
<Compile Include="Models\CipherString.cs" />
|
||||
<Compile Include="Models\Data\AttachmentData.cs" />
|
||||
<Compile Include="Models\Attachment.cs" />
|
||||
<Compile Include="Models\Field.cs" />
|
||||
<Compile Include="Models\Identity.cs" />
|
||||
<Compile Include="Models\Login.cs" />
|
||||
<Compile Include="Models\Page\VaultAttachmentsPageModel.cs" />
|
||||
<Compile Include="Models\SecureNote.cs" />
|
||||
<Compile Include="Models\SymmetricCryptoKey.cs" />
|
||||
<Compile Include="Models\Data\SettingsData.cs" />
|
||||
<Compile Include="Models\Data\FolderData.cs" />
|
||||
<Compile Include="Abstractions\IDataObject.cs" />
|
||||
<Compile Include="Models\Data\LoginData.cs" />
|
||||
<Compile Include="Models\Data\CipherData.cs" />
|
||||
<Compile Include="Models\DomainName.cs" />
|
||||
<Compile Include="Models\Folder.cs" />
|
||||
<Compile Include="Models\LoginResult.cs" />
|
||||
@@ -141,8 +152,8 @@
|
||||
<Compile Include="Models\Page\PasswordGeneratorPageModel.cs" />
|
||||
<Compile Include="Models\PlatformCulture.cs" />
|
||||
<Compile Include="Models\PushNotification.cs" />
|
||||
<Compile Include="Models\Login.cs" />
|
||||
<Compile Include="Models\Page\VaultViewLoginPageModel.cs" />
|
||||
<Compile Include="Models\Cipher.cs" />
|
||||
<Compile Include="Models\Page\VaultViewCipherPageModel.cs" />
|
||||
<Compile Include="Pages\HomePage.cs" />
|
||||
<Compile Include="Pages\Lock\BaseLockPage.cs" />
|
||||
<Compile Include="Pages\Lock\LockPasswordPage.cs" />
|
||||
@@ -169,10 +180,10 @@
|
||||
<Compile Include="Pages\Settings\SettingsPage.cs" />
|
||||
<Compile Include="Pages\Settings\SettingsListFoldersPage.cs" />
|
||||
<Compile Include="Pages\Vault\VaultCustomFieldsPage.cs" />
|
||||
<Compile Include="Pages\Vault\VaultAutofillListLoginsPage.cs" />
|
||||
<Compile Include="Pages\Vault\VaultAutofillListCiphersPage.cs" />
|
||||
<Compile Include="Pages\Vault\VaultAttachmentsPage.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Abstractions\Repositories\ILoginRepository.cs" />
|
||||
<Compile Include="Abstractions\Repositories\ICipherRepository.cs" />
|
||||
<Compile Include="Repositories\AttachmentRepository.cs" />
|
||||
<Compile Include="Repositories\SyncApiRepository.cs" />
|
||||
<Compile Include="Repositories\TwoFactorApiRepository.cs" />
|
||||
@@ -189,7 +200,7 @@
|
||||
<Compile Include="Abstractions\Repositories\ICipherApiRepository.cs" />
|
||||
<Compile Include="Repositories\SettingsRepository.cs" />
|
||||
<Compile Include="Repositories\FolderApiRepository.cs" />
|
||||
<Compile Include="Repositories\LoginRepository.cs" />
|
||||
<Compile Include="Repositories\CipherRepository.cs" />
|
||||
<Compile Include="Repositories\FolderRepository.cs" />
|
||||
<Compile Include="Abstractions\Repositories\IFolderRepository.cs" />
|
||||
<Compile Include="Abstractions\Repositories\IRepository.cs" />
|
||||
@@ -203,6 +214,11 @@
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>AppResources.da.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Resources\AppResources.de.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>AppResources.de.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Resources\AppResources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
@@ -337,16 +353,16 @@
|
||||
<Compile Include="Abstractions\Services\ISyncService.cs" />
|
||||
<Compile Include="Abstractions\Services\IPasswordGenerationService.cs" />
|
||||
<Compile Include="Services\SyncService.cs" />
|
||||
<Compile Include="Services\LoginService.cs" />
|
||||
<Compile Include="Services\CipherService.cs" />
|
||||
<Compile Include="Services\AuthService.cs" />
|
||||
<Compile Include="Services\CryptoService.cs" />
|
||||
<Compile Include="Models\Page\VaultListPageModel.cs" />
|
||||
<Compile Include="Pages\LoginPage.cs" />
|
||||
<Compile Include="Pages\Settings\SettingsAddFolderPage.cs" />
|
||||
<Compile Include="Pages\Vault\VaultAddLoginPage.cs" />
|
||||
<Compile Include="Pages\Vault\VaultViewLoginPage.cs" />
|
||||
<Compile Include="Pages\Vault\VaultEditLoginPage.cs" />
|
||||
<Compile Include="Pages\Vault\VaultListLoginsPage.cs" />
|
||||
<Compile Include="Pages\Vault\VaultAddCipherPage.cs" />
|
||||
<Compile Include="Pages\Vault\VaultViewCipherPage.cs" />
|
||||
<Compile Include="Pages\Vault\VaultEditCipherPage.cs" />
|
||||
<Compile Include="Pages\Vault\VaultListCiphersPage.cs" />
|
||||
<Compile Include="Services\PasswordGenerationService.cs" />
|
||||
<Compile Include="Utilities\Base32.cs" />
|
||||
<Compile Include="Utilities\Crypto.cs" />
|
||||
@@ -355,6 +371,7 @@
|
||||
<Compile Include="Utilities\Extentions.cs" />
|
||||
<Compile Include="Utilities\ExtendedObservableCollection.cs" />
|
||||
<Compile Include="Utilities\ApiHttpClient.cs" />
|
||||
<Compile Include="Utilities\PushNotificationContants.cs" />
|
||||
<Compile Include="Utilities\TokenHttpRequestMessage.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -370,6 +387,10 @@
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>AppResources.da.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\AppResources.de.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>AppResources.de.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources\AppResources.es.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>AppResources.es.Designer.cs</LastGenOutput>
|
||||
@@ -528,20 +549,12 @@
|
||||
<Reference Include="Plugin.Settings.Abstractions, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Xam.Plugins.Settings.3.0.1\lib\netstandard1.0\Plugin.Settings.Abstractions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PushNotification.Plugin, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Xam.Plugin.PushNotification.1.2.4\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\PushNotification.Plugin.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="PushNotification.Plugin.Abstractions, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Xam.Plugin.PushNotification.1.2.4\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\PushNotification.Plugin.Abstractions.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Splat, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Splat.1.6.2\lib\Portable-net45+win+wpa81+wp80\Splat.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SQLite-net, Version=1.4.118.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\sqlite-net-pcl.1.4.118\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLite-net.dll</HintPath>
|
||||
<Reference Include="SQLite-net, Version=1.5.166.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\sqlite-net-pcl.1.5.166-beta\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLite-net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SQLitePCLRaw.batteries_green, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a84b7dcfb1391f7f, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\SQLitePCLRaw.bundle_green.1.1.8\lib\portable-net45+netcore45+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.batteries_green.dll</HintPath>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
public const string SettingPinUnlockOn = "setting:pinUnlockOn";
|
||||
public const string SettingLockSeconds = "setting:lockSeconds";
|
||||
public const string SettingGaOptOut = "setting:googleAnalyticsOptOut";
|
||||
public const string SettingDisableWebsiteIcons = "setting:disableWebsiteIcons";
|
||||
public const string SettingDisableTotpCopy = "setting:disableAutoCopyTotp";
|
||||
public const string AutofillPersistNotification = "setting:persistNotification";
|
||||
public const string AutofillPasswordField = "setting:autofillPasswordField";
|
||||
@@ -39,6 +40,7 @@
|
||||
public const string WebVaultUrl = "other:webVaultUrl";
|
||||
public const string ApiUrl = "other:apiUrl";
|
||||
public const string IdentityUrl = "other:identityUrl";
|
||||
public const string IconsUrl = "other:iconsUrl";
|
||||
|
||||
public const int SelectFileRequestCode = 42;
|
||||
public const int SelectFilePermissionRequestCode = 43;
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Bit.App.Controls
|
||||
|
||||
protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
|
||||
{
|
||||
if(!VerticalOptions.Expands)
|
||||
if(!VerticalOptions.Expands && Device.RuntimePlatform != Device.Windows)
|
||||
{
|
||||
var reflectionService = Resolver.Resolve<IReflectionService>();
|
||||
var baseBaseOnSizeRequest = reflectionService.GetVisualElementOnSizeRequest(this);
|
||||
|
||||
@@ -21,8 +21,6 @@ namespace Bit.App.Controls
|
||||
Thickness? containerPadding = null,
|
||||
bool useButton = false)
|
||||
{
|
||||
_nextElement = nextElement;
|
||||
|
||||
if(!useLabelAsPlaceholder)
|
||||
{
|
||||
Label = new Label
|
||||
@@ -50,10 +48,7 @@ namespace Bit.App.Controls
|
||||
Entry.Placeholder = labelText;
|
||||
}
|
||||
|
||||
if(nextElement != null)
|
||||
{
|
||||
Entry.ReturnType = Enums.ReturnType.Next;
|
||||
}
|
||||
NextElement = nextElement;
|
||||
|
||||
var imageStackLayout = new StackLayout
|
||||
{
|
||||
@@ -129,6 +124,7 @@ namespace Bit.App.Controls
|
||||
{
|
||||
Button.Padding = new Thickness(0);
|
||||
Button.BackgroundColor = Color.Transparent;
|
||||
Button.WidthRequest = 40;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +134,22 @@ namespace Bit.App.Controls
|
||||
public Label Label { get; private set; }
|
||||
public ExtendedEntry Entry { get; private set; }
|
||||
public ExtendedButton Button { get; private set; }
|
||||
public VisualElement NextElement
|
||||
{
|
||||
get => _nextElement;
|
||||
set
|
||||
{
|
||||
_nextElement = value;
|
||||
if(_nextElement != null && Entry != null)
|
||||
{
|
||||
Entry.ReturnType = Enums.ReturnType.Next;
|
||||
}
|
||||
else if(Entry != null)
|
||||
{
|
||||
Entry.ReturnType = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void InitEvents()
|
||||
{
|
||||
@@ -150,7 +162,7 @@ namespace Bit.App.Controls
|
||||
{
|
||||
_tgr.Tapped += Tgr_Tapped;
|
||||
}
|
||||
|
||||
|
||||
Tapped += FormEntryCell_Tapped;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using FFImageLoading.Forms;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Controls
|
||||
@@ -7,6 +8,17 @@ namespace Bit.App.Controls
|
||||
{
|
||||
public LabeledDetailCell()
|
||||
{
|
||||
Icon = new CachedImage
|
||||
{
|
||||
WidthRequest = 20,
|
||||
HeightRequest = 20,
|
||||
HorizontalOptions = LayoutOptions.Center,
|
||||
VerticalOptions = LayoutOptions.Center,
|
||||
ErrorPlaceholder = "login.png",
|
||||
CacheDuration = TimeSpan.FromDays(30),
|
||||
BitmapOptimizations = true
|
||||
};
|
||||
|
||||
Label = new Label
|
||||
{
|
||||
LineBreakMode = LineBreakMode.TailTruncation,
|
||||
@@ -45,21 +57,24 @@ namespace Bit.App.Controls
|
||||
{
|
||||
ColumnSpacing = 0,
|
||||
RowSpacing = 0,
|
||||
Padding = new Thickness(15, 3, 0, 3)
|
||||
Padding = new Thickness(3, 3, 0, 3)
|
||||
};
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(40, GridUnitType.Absolute) });
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(60, GridUnitType.Absolute) });
|
||||
grid.Children.Add(Label, 0, 0);
|
||||
grid.Children.Add(Detail, 0, 1);
|
||||
grid.Children.Add(LabelIcon, 1, 0);
|
||||
grid.Children.Add(LabelIcon2, 2, 0);
|
||||
grid.Children.Add(Button, 3, 0);
|
||||
Grid.SetColumnSpan(Detail, 3);
|
||||
grid.Children.Add(Icon, 0, 0);
|
||||
grid.Children.Add(Label, 1, 0);
|
||||
grid.Children.Add(Detail, 1, 1);
|
||||
grid.Children.Add(LabelIcon, 2, 0);
|
||||
grid.Children.Add(LabelIcon2, 3, 0);
|
||||
grid.Children.Add(Button, 4, 0);
|
||||
Grid.SetRowSpan(Icon, 2);
|
||||
Grid.SetRowSpan(Button, 2);
|
||||
Grid.SetColumnSpan(Detail, 3);
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
@@ -69,6 +84,7 @@ namespace Bit.App.Controls
|
||||
View = grid;
|
||||
}
|
||||
|
||||
public CachedImage Icon { get; private set; }
|
||||
public Label Label { get; private set; }
|
||||
public Label Detail { get; private set; }
|
||||
public CachedImage LabelIcon { get; private set; }
|
||||
|
||||
@@ -7,8 +7,8 @@ namespace Bit.App.Controls
|
||||
public LabeledValueCell(
|
||||
string labelText = null,
|
||||
string valueText = null,
|
||||
string button1Text = null,
|
||||
string button2Text = null,
|
||||
string button1Image = null,
|
||||
string button2Image = null,
|
||||
string subText = null)
|
||||
{
|
||||
var containerStackLayout = new StackLayout
|
||||
@@ -69,11 +69,11 @@ namespace Bit.App.Controls
|
||||
buttonStackLayout.Children.Add(Sub);
|
||||
}
|
||||
|
||||
if(button1Text != null)
|
||||
if(button1Image != null)
|
||||
{
|
||||
Button1 = new ExtendedButton
|
||||
{
|
||||
Text = button1Text,
|
||||
Image = button1Image,
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.Center,
|
||||
Margin = new Thickness(0)
|
||||
@@ -82,11 +82,11 @@ namespace Bit.App.Controls
|
||||
buttonStackLayout.Children.Add(Button1);
|
||||
}
|
||||
|
||||
if(button2Text != null)
|
||||
if(button2Image != null)
|
||||
{
|
||||
Button2 = new ExtendedButton
|
||||
{
|
||||
Text = button2Text,
|
||||
Image = button2Image,
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.Center,
|
||||
Margin = new Thickness(0)
|
||||
@@ -103,11 +103,13 @@ namespace Bit.App.Controls
|
||||
{
|
||||
Button1.Padding = new Thickness(0);
|
||||
Button1.BackgroundColor = Color.Transparent;
|
||||
Button1.WidthRequest = 40;
|
||||
}
|
||||
if(Button2 != null)
|
||||
{
|
||||
Button2.Padding = new Thickness(0);
|
||||
Button2.BackgroundColor = Color.Transparent;
|
||||
Button2.WidthRequest = 40;
|
||||
}
|
||||
|
||||
containerStackLayout.AdjustPaddingForDevice();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Bit.App.Models.Page;
|
||||
using FFImageLoading.Forms;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
@@ -6,31 +7,46 @@ namespace Bit.App.Controls
|
||||
{
|
||||
public class VaultListViewCell : LabeledDetailCell
|
||||
{
|
||||
public static readonly BindableProperty LoginParameterProperty = BindableProperty.Create(nameof(LoginParameter),
|
||||
typeof(VaultListPageModel.Login), typeof(VaultListViewCell), null);
|
||||
public static readonly BindableProperty CipherParameterProperty = BindableProperty.Create(nameof(CipherParameter),
|
||||
typeof(VaultListPageModel.Cipher), typeof(VaultListViewCell), null);
|
||||
|
||||
public VaultListViewCell(Action<VaultListPageModel.Login> moreClickedAction)
|
||||
public VaultListViewCell(Action<VaultListPageModel.Cipher> moreClickedAction)
|
||||
{
|
||||
SetBinding(LoginParameterProperty, new Binding("."));
|
||||
Label.SetBinding(Label.TextProperty, nameof(VaultListPageModel.Login.Name));
|
||||
Detail.SetBinding(Label.TextProperty, nameof(VaultListPageModel.Login.Username));
|
||||
LabelIcon.SetBinding(VisualElement.IsVisibleProperty, nameof(VaultListPageModel.Login.Shared));
|
||||
LabelIcon2.SetBinding(VisualElement.IsVisibleProperty, nameof(VaultListPageModel.Login.HasAttachments));
|
||||
SetBinding(CipherParameterProperty, new Binding("."));
|
||||
Label.SetBinding(Label.TextProperty, nameof(VaultListPageModel.Cipher.Name));
|
||||
Detail.SetBinding(Label.TextProperty, nameof(VaultListPageModel.Cipher.Subtitle));
|
||||
LabelIcon.SetBinding(VisualElement.IsVisibleProperty, nameof(VaultListPageModel.Cipher.Shared));
|
||||
LabelIcon2.SetBinding(VisualElement.IsVisibleProperty, nameof(VaultListPageModel.Cipher.HasAttachments));
|
||||
|
||||
Button.Image = "more";
|
||||
Button.Command = new Command(() => moreClickedAction?.Invoke(LoginParameter));
|
||||
Button.Image = "more.png";
|
||||
Button.Command = new Command(() => moreClickedAction?.Invoke(CipherParameter));
|
||||
Button.BackgroundColor = Color.Transparent;
|
||||
|
||||
LabelIcon.Source = "share";
|
||||
LabelIcon2.Source = "paperclip";
|
||||
LabelIcon.Source = "share.png";
|
||||
LabelIcon2.Source = "paperclip.png";
|
||||
|
||||
BackgroundColor = Color.White;
|
||||
}
|
||||
|
||||
public VaultListPageModel.Login LoginParameter
|
||||
public VaultListPageModel.Cipher CipherParameter
|
||||
{
|
||||
get { return GetValue(LoginParameterProperty) as VaultListPageModel.Login; }
|
||||
set { SetValue(LoginParameterProperty, value); }
|
||||
get { return GetValue(CipherParameterProperty) as VaultListPageModel.Cipher; }
|
||||
set { SetValue(CipherParameterProperty, value); }
|
||||
}
|
||||
|
||||
protected override void OnBindingContextChanged()
|
||||
{
|
||||
Icon.Source = null;
|
||||
if(BindingContext is VaultListPageModel.Cipher item)
|
||||
{
|
||||
if(item.Type == Enums.CipherType.Login)
|
||||
{
|
||||
Icon.LoadingPlaceholder = "login.png";
|
||||
}
|
||||
Icon.Source = item.Icon;
|
||||
}
|
||||
|
||||
base.OnBindingContextChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
//Folder = 0,
|
||||
Login = 1,
|
||||
SecureNote = 2,
|
||||
Card = 3
|
||||
Card = 3,
|
||||
Identity = 4
|
||||
}
|
||||
}
|
||||
|
||||
9
src/App/Enums/DeviceType.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum DeviceType
|
||||
{
|
||||
Android = 0,
|
||||
iOS = 1,
|
||||
UWP = 16
|
||||
}
|
||||
}
|
||||
7
src/App/Enums/SecureNoteType.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Bit.App.Enums
|
||||
{
|
||||
public enum SecureNoteType : byte
|
||||
{
|
||||
Generic = 0
|
||||
}
|
||||
}
|
||||
12
src/App/Models/Api/CardDataModel.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class CardDataModel : CipherDataModel
|
||||
{
|
||||
public string CardholderName { get; set; }
|
||||
public string Brand { get; set; }
|
||||
public string Number { get; set; }
|
||||
public string ExpMonth { get; set; }
|
||||
public string ExpYear { get; set; }
|
||||
public string Code { get; set; }
|
||||
}
|
||||
}
|
||||
24
src/App/Models/Api/IdentityDataModel.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class IdentityDataModel : CipherDataModel
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string FirstName { get; set; }
|
||||
public string MiddleName { get; set; }
|
||||
public string LastName { get; set; }
|
||||
public string Address1 { get; set; }
|
||||
public string Address2 { get; set; }
|
||||
public string Address3 { get; set; }
|
||||
public string City { get; set; }
|
||||
public string State { get; set; }
|
||||
public string PostalCode { get; set; }
|
||||
public string Country { get; set; }
|
||||
public string Company { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Phone { get; set; }
|
||||
public string SSN { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string PassportNumber { get; set; }
|
||||
public string LicenseNumber { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -6,18 +6,18 @@ namespace Bit.App.Models.Api
|
||||
{
|
||||
public class CipherRequest
|
||||
{
|
||||
public CipherRequest(Login login)
|
||||
public CipherRequest(Cipher cipher)
|
||||
{
|
||||
Type = CipherType.Login;
|
||||
OrganizationId = login.OrganizationId;
|
||||
FolderId = login.FolderId;
|
||||
Name = login.Name?.EncryptedString;
|
||||
Notes = login.Notes?.EncryptedString;
|
||||
Favorite = login.Favorite;
|
||||
Type = cipher.Type;
|
||||
OrganizationId = cipher.OrganizationId;
|
||||
FolderId = cipher.FolderId;
|
||||
Name = cipher.Name?.EncryptedString;
|
||||
Notes = cipher.Notes?.EncryptedString;
|
||||
Favorite = cipher.Favorite;
|
||||
|
||||
if(login.Fields != null)
|
||||
if(cipher.Fields != null)
|
||||
{
|
||||
Fields = login.Fields.Select(f => new FieldDataModel
|
||||
Fields = cipher.Fields.Select(f => new FieldDataModel
|
||||
{
|
||||
Name = f.Name?.EncryptedString,
|
||||
Value = f.Value?.EncryptedString,
|
||||
@@ -28,7 +28,16 @@ namespace Bit.App.Models.Api
|
||||
switch(Type)
|
||||
{
|
||||
case CipherType.Login:
|
||||
Login = new LoginType(login);
|
||||
Login = new LoginType(cipher);
|
||||
break;
|
||||
case CipherType.Card:
|
||||
Card = new CardType(cipher);
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
Identity = new IdentityType(cipher);
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
SecureNote = new SecureNoteType(cipher);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -42,16 +51,20 @@ namespace Bit.App.Models.Api
|
||||
public string Name { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public IEnumerable<FieldDataModel> Fields { get; set; }
|
||||
|
||||
public LoginType Login { get; set; }
|
||||
public CardType Card { get; set; }
|
||||
public IdentityType Identity { get; set; }
|
||||
public SecureNoteType SecureNote { get; set; }
|
||||
|
||||
public class LoginType
|
||||
{
|
||||
public LoginType(Login login)
|
||||
public LoginType(Cipher cipher)
|
||||
{
|
||||
Uri = login.Uri?.EncryptedString;
|
||||
Username = login.Username?.EncryptedString;
|
||||
Password = login.Password?.EncryptedString;
|
||||
Totp = login.Totp?.EncryptedString;
|
||||
Uri = cipher.Login.Uri?.EncryptedString;
|
||||
Username = cipher.Login.Username?.EncryptedString;
|
||||
Password = cipher.Login.Password?.EncryptedString;
|
||||
Totp = cipher.Login.Totp?.EncryptedString;
|
||||
}
|
||||
|
||||
public string Uri { get; set; }
|
||||
@@ -59,5 +72,79 @@ namespace Bit.App.Models.Api
|
||||
public string Password { get; set; }
|
||||
public string Totp { get; set; }
|
||||
}
|
||||
|
||||
public class CardType
|
||||
{
|
||||
public CardType(Cipher cipher)
|
||||
{
|
||||
CardholderName = cipher.Card.CardholderName?.EncryptedString;
|
||||
Brand = cipher.Card.Brand?.EncryptedString;
|
||||
Number = cipher.Card.Number?.EncryptedString;
|
||||
ExpMonth = cipher.Card.ExpMonth?.EncryptedString;
|
||||
ExpYear = cipher.Card.ExpYear?.EncryptedString;
|
||||
Code = cipher.Card.Code?.EncryptedString;
|
||||
}
|
||||
|
||||
public string CardholderName { get; set; }
|
||||
public string Brand { get; set; }
|
||||
public string Number { get; set; }
|
||||
public string ExpMonth { get; set; }
|
||||
public string ExpYear { get; set; }
|
||||
public string Code { get; set; }
|
||||
}
|
||||
|
||||
public class IdentityType
|
||||
{
|
||||
public IdentityType(Cipher cipher)
|
||||
{
|
||||
Title = cipher.Identity.Title?.EncryptedString;
|
||||
FirstName = cipher.Identity.FirstName?.EncryptedString;
|
||||
MiddleName = cipher.Identity.MiddleName?.EncryptedString;
|
||||
LastName = cipher.Identity.LastName?.EncryptedString;
|
||||
Address1 = cipher.Identity.Address1?.EncryptedString;
|
||||
Address2 = cipher.Identity.Address2?.EncryptedString;
|
||||
Address3 = cipher.Identity.Address3?.EncryptedString;
|
||||
City = cipher.Identity.City?.EncryptedString;
|
||||
State = cipher.Identity.State?.EncryptedString;
|
||||
PostalCode = cipher.Identity.PostalCode?.EncryptedString;
|
||||
Country = cipher.Identity.Country?.EncryptedString;
|
||||
Company = cipher.Identity.Company?.EncryptedString;
|
||||
Email = cipher.Identity.Email?.EncryptedString;
|
||||
Phone = cipher.Identity.Phone?.EncryptedString;
|
||||
SSN = cipher.Identity.SSN?.EncryptedString;
|
||||
Username = cipher.Identity.Username?.EncryptedString;
|
||||
PassportNumber = cipher.Identity.PassportNumber?.EncryptedString;
|
||||
LicenseNumber = cipher.Identity.LicenseNumber?.EncryptedString;
|
||||
}
|
||||
|
||||
public string Title { get; set; }
|
||||
public string FirstName { get; set; }
|
||||
public string MiddleName { get; set; }
|
||||
public string LastName { get; set; }
|
||||
public string Address1 { get; set; }
|
||||
public string Address2 { get; set; }
|
||||
public string Address3 { get; set; }
|
||||
public string City { get; set; }
|
||||
public string State { get; set; }
|
||||
public string PostalCode { get; set; }
|
||||
public string Country { get; set; }
|
||||
public string Company { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Phone { get; set; }
|
||||
public string SSN { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string PassportNumber { get; set; }
|
||||
public string LicenseNumber { get; set; }
|
||||
}
|
||||
|
||||
public class SecureNoteType
|
||||
{
|
||||
public SecureNoteType(Cipher cipher)
|
||||
{
|
||||
Type = cipher.SecureNote.Type;
|
||||
}
|
||||
|
||||
public Enums.SecureNoteType Type { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Bit.App.Abstractions;
|
||||
using PushNotification.Plugin.Abstractions;
|
||||
using Bit.App.Enums;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Models.Api
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using PushNotification.Plugin.Abstractions;
|
||||
using Bit.App.Enums;
|
||||
using System;
|
||||
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
|
||||
9
src/App/Models/Api/SecureNoteDataModel.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Bit.App.Enums;
|
||||
|
||||
namespace Bit.App.Models.Api
|
||||
{
|
||||
public class SecureNoteDataModel : CipherDataModel
|
||||
{
|
||||
public SecureNoteType Type { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -32,11 +32,6 @@ namespace Bit.App.Models
|
||||
public long Size { get; set; }
|
||||
public string SizeName { get; set; }
|
||||
|
||||
public AttachmentData ToAttachmentData(string loginId)
|
||||
{
|
||||
return new AttachmentData(this, loginId);
|
||||
}
|
||||
|
||||
private void SetSize(string sizeString)
|
||||
{
|
||||
long size;
|
||||
|
||||
31
src/App/Models/Card.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Bit.App.Models.Api;
|
||||
using Bit.App.Models.Data;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Bit.App.Models
|
||||
{
|
||||
public class Card
|
||||
{
|
||||
public Card() { }
|
||||
|
||||
public Card(CipherData data)
|
||||
{
|
||||
var deserializedData = JsonConvert.DeserializeObject<CardDataModel>(data.Data);
|
||||
|
||||
CardholderName = deserializedData.CardholderName != null ?
|
||||
new CipherString(deserializedData.CardholderName) : null;
|
||||
Brand = deserializedData.Brand != null ? new CipherString(deserializedData.Brand) : null;
|
||||
Number = deserializedData.Number != null ? new CipherString(deserializedData.Number) : null;
|
||||
ExpMonth = deserializedData.ExpMonth != null ? new CipherString(deserializedData.ExpMonth) : null;
|
||||
ExpYear = deserializedData.ExpYear != null ? new CipherString(deserializedData.ExpYear) : null;
|
||||
Code = deserializedData.Code != null ? new CipherString(deserializedData.Code) : null;
|
||||
}
|
||||
|
||||
public CipherString CardholderName { get; set; }
|
||||
public CipherString Brand { get; set; }
|
||||
public CipherString Number { get; set; }
|
||||
public CipherString ExpMonth { get; set; }
|
||||
public CipherString ExpYear { get; set; }
|
||||
public CipherString Code { get; set; }
|
||||
}
|
||||
}
|
||||
76
src/App/Models/Cipher.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using Bit.App.Enums;
|
||||
using Bit.App.Models.Api;
|
||||
using Bit.App.Models.Data;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Bit.App.Models
|
||||
{
|
||||
public class Cipher
|
||||
{
|
||||
public Cipher()
|
||||
{ }
|
||||
|
||||
public Cipher(CipherData data, IEnumerable<AttachmentData> attachments = null)
|
||||
{
|
||||
Id = data.Id;
|
||||
UserId = data.UserId;
|
||||
OrganizationId = data.OrganizationId;
|
||||
FolderId = data.FolderId;
|
||||
Type = data.Type;
|
||||
Name = data.Name != null ? new CipherString(data.Name) : null;
|
||||
Notes = data.Notes != null ? new CipherString(data.Notes) : null;
|
||||
Favorite = data.Favorite;
|
||||
Edit = data.Edit;
|
||||
OrganizationUseTotp = data.OrganizationUseTotp;
|
||||
Attachments = attachments?.Select(a => new Attachment(a));
|
||||
|
||||
switch(Type)
|
||||
{
|
||||
case CipherType.Login:
|
||||
Login = new Login(data);
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
SecureNote = new SecureNote(data);
|
||||
break;
|
||||
case CipherType.Card:
|
||||
Card = new Card(data);
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
Identity = new Identity(data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(data.Fields))
|
||||
{
|
||||
try
|
||||
{
|
||||
var fieldModels = JsonConvert.DeserializeObject<IEnumerable<FieldDataModel>>(data.Fields);
|
||||
Fields = fieldModels?.Select(f => new Field(f));
|
||||
}
|
||||
catch(JsonSerializationException) { }
|
||||
}
|
||||
}
|
||||
|
||||
public string Id { get; set; }
|
||||
public string UserId { get; set; }
|
||||
public string OrganizationId { get; set; }
|
||||
public string FolderId { get; set; }
|
||||
public CipherType Type { get; set; }
|
||||
public CipherString Name { get; set; }
|
||||
public CipherString Notes { get; set; }
|
||||
public IEnumerable<Field> Fields { get; set; }
|
||||
public bool Favorite { get; set; }
|
||||
public bool Edit { get; set; }
|
||||
public bool OrganizationUseTotp { get; set; }
|
||||
public IEnumerable<Attachment> Attachments { get; set; }
|
||||
|
||||
public Login Login { get; set; }
|
||||
public Identity Identity { get; set; }
|
||||
public Card Card { get; set; }
|
||||
public SecureNote SecureNote { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -10,20 +10,20 @@ namespace Bit.App.Models.Data
|
||||
public AttachmentData()
|
||||
{ }
|
||||
|
||||
public AttachmentData(Attachment attachment, string loginId)
|
||||
public AttachmentData(Attachment attachment, string cipherId)
|
||||
{
|
||||
Id = attachment.Id;
|
||||
LoginId = loginId;
|
||||
LoginId = cipherId;
|
||||
Url = attachment.Url;
|
||||
FileName = attachment.FileName?.EncryptedString;
|
||||
Size = attachment.Size.ToString();
|
||||
SizeName = attachment.SizeName;
|
||||
}
|
||||
|
||||
public AttachmentData(AttachmentResponse response, string loginId)
|
||||
public AttachmentData(AttachmentResponse response, string cipherId)
|
||||
{
|
||||
Id = response.Id;
|
||||
LoginId = loginId;
|
||||
LoginId = cipherId;
|
||||
Url = response.Url;
|
||||
FileName = response.FileName;
|
||||
Size = response.Size;
|
||||
@@ -32,6 +32,7 @@ namespace Bit.App.Models.Data
|
||||
|
||||
[PrimaryKey]
|
||||
public string Id { get; set; }
|
||||
// Really should be called CipherId
|
||||
[Indexed]
|
||||
public string LoginId { get; set; }
|
||||
public string Url { get; set; }
|
||||
|
||||
100
src/App/Models/Data/CipherData.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using SQLite;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Models.Api;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq;
|
||||
using Bit.App.Enums;
|
||||
|
||||
namespace Bit.App.Models.Data
|
||||
{
|
||||
// Old table that has just carried over for backward compat. sake. Should really be "Cipher"
|
||||
[Table("Site")]
|
||||
public class CipherData : IDataObject<string>
|
||||
{
|
||||
public CipherData()
|
||||
{ }
|
||||
|
||||
public CipherData(CipherResponse cipher, string userId)
|
||||
{
|
||||
Id = cipher.Id;
|
||||
FolderId = cipher.FolderId;
|
||||
UserId = userId;
|
||||
OrganizationId = cipher.OrganizationId;
|
||||
Favorite = cipher.Favorite;
|
||||
Edit = cipher.Edit;
|
||||
OrganizationUseTotp = cipher.OrganizationUseTotp;
|
||||
RevisionDateTime = cipher.RevisionDate;
|
||||
Type = cipher.Type;
|
||||
Data = JsonConvert.SerializeObject(cipher.Data);
|
||||
|
||||
CipherDataModel cipherData = null;
|
||||
switch(cipher.Type)
|
||||
{
|
||||
case CipherType.Login:
|
||||
var loginData = cipher.Data.ToObject<LoginDataModel>();
|
||||
cipherData = loginData;
|
||||
|
||||
Uri = loginData.Uri;
|
||||
Username = loginData.Username;
|
||||
Password = loginData.Password;
|
||||
Totp = loginData.Totp;
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
var noteData = cipher.Data.ToObject<SecureNoteDataModel>();
|
||||
cipherData = noteData;
|
||||
|
||||
SecureNoteType = noteData.Type;
|
||||
break;
|
||||
case CipherType.Card:
|
||||
var cardData = cipher.Data.ToObject<CardDataModel>();
|
||||
cipherData = cardData;
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
var idData = cipher.Data.ToObject<IdentityDataModel>();
|
||||
cipherData = idData;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException(nameof(cipher.Type));
|
||||
}
|
||||
|
||||
Name = cipherData.Name;
|
||||
Notes = cipherData.Notes;
|
||||
|
||||
if(cipherData.Fields != null && cipherData.Fields.Any())
|
||||
{
|
||||
try
|
||||
{
|
||||
Fields = JsonConvert.SerializeObject(cipherData.Fields);
|
||||
}
|
||||
catch(JsonSerializationException) { }
|
||||
}
|
||||
}
|
||||
|
||||
[PrimaryKey]
|
||||
public string Id { get; set; }
|
||||
public string FolderId { get; set; }
|
||||
[Indexed]
|
||||
public string UserId { get; set; }
|
||||
public string OrganizationId { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public string Fields { get; set; }
|
||||
public bool Favorite { get; set; }
|
||||
public bool Edit { get; set; }
|
||||
public bool OrganizationUseTotp { get; set; }
|
||||
public DateTime RevisionDateTime { get; set; } = DateTime.UtcNow;
|
||||
[Indexed]
|
||||
public CipherType Type { get; set; } = CipherType.Login;
|
||||
public string Data { get; set; }
|
||||
|
||||
// Login metadata
|
||||
public string Uri { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string Totp { get; set; }
|
||||
|
||||
// Secure Note metadata
|
||||
public SecureNoteType? SecureNoteType { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
using System;
|
||||
using SQLite;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Models.Api;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq;
|
||||
|
||||
namespace Bit.App.Models.Data
|
||||
{
|
||||
[Table("Site")]
|
||||
public class LoginData : IDataObject<string>
|
||||
{
|
||||
public LoginData()
|
||||
{ }
|
||||
|
||||
public LoginData(CipherResponse cipher, string userId)
|
||||
{
|
||||
if(cipher.Type != Enums.CipherType.Login)
|
||||
{
|
||||
throw new ArgumentException(nameof(cipher.Type));
|
||||
}
|
||||
|
||||
var data = cipher.Data.ToObject<LoginDataModel>();
|
||||
|
||||
Id = cipher.Id;
|
||||
FolderId = cipher.FolderId;
|
||||
UserId = userId;
|
||||
OrganizationId = cipher.OrganizationId;
|
||||
Name = data.Name;
|
||||
Uri = data.Uri;
|
||||
Username = data.Username;
|
||||
Password = data.Password;
|
||||
Notes = data.Notes;
|
||||
Totp = data.Totp;
|
||||
Favorite = cipher.Favorite;
|
||||
Edit = cipher.Edit;
|
||||
OrganizationUseTotp = cipher.OrganizationUseTotp;
|
||||
RevisionDateTime = cipher.RevisionDate;
|
||||
|
||||
if(data.Fields != null && data.Fields.Any())
|
||||
{
|
||||
try
|
||||
{
|
||||
Fields = JsonConvert.SerializeObject(data.Fields);
|
||||
}
|
||||
catch(JsonSerializationException) { }
|
||||
}
|
||||
}
|
||||
|
||||
[PrimaryKey]
|
||||
public string Id { get; set; }
|
||||
public string FolderId { get; set; }
|
||||
[Indexed]
|
||||
public string UserId { get; set; }
|
||||
public string OrganizationId { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Uri { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public string Totp { get; set; }
|
||||
public string Fields { get; set; }
|
||||
public bool Favorite { get; set; }
|
||||
public bool Edit { get; set; }
|
||||
public bool OrganizationUseTotp { get; set; }
|
||||
public DateTime RevisionDateTime { get; set; } = DateTime.UtcNow;
|
||||
|
||||
public Login ToLogin()
|
||||
{
|
||||
return new Login(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
56
src/App/Models/Identity.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using Bit.App.Models.Api;
|
||||
using Bit.App.Models.Data;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Bit.App.Models
|
||||
{
|
||||
public class Identity
|
||||
{
|
||||
public Identity() { }
|
||||
|
||||
public Identity(CipherData data)
|
||||
{
|
||||
var deserializedData = JsonConvert.DeserializeObject<IdentityDataModel>(data.Data);
|
||||
|
||||
Title = deserializedData.Title != null ? new CipherString(deserializedData.Title) : null;
|
||||
FirstName = deserializedData.FirstName != null ? new CipherString(deserializedData.FirstName) : null;
|
||||
MiddleName = deserializedData.MiddleName != null ? new CipherString(deserializedData.MiddleName) : null;
|
||||
LastName = deserializedData.LastName != null ? new CipherString(deserializedData.LastName) : null;
|
||||
Address1 = deserializedData.Address1 != null ? new CipherString(deserializedData.Address1) : null;
|
||||
Address2 = deserializedData.Address2 != null ? new CipherString(deserializedData.Address2) : null;
|
||||
Address3 = deserializedData.Address3 != null ? new CipherString(deserializedData.Address3) : null;
|
||||
City = deserializedData.City != null ? new CipherString(deserializedData.City) : null;
|
||||
State = deserializedData.State != null ? new CipherString(deserializedData.State) : null;
|
||||
PostalCode = deserializedData.PostalCode != null ? new CipherString(deserializedData.PostalCode) : null;
|
||||
Country = deserializedData.Country != null ? new CipherString(deserializedData.Country) : null;
|
||||
Company = deserializedData.Company != null ? new CipherString(deserializedData.Company) : null;
|
||||
Email = deserializedData.Email != null ? new CipherString(deserializedData.Email) : null;
|
||||
Phone = deserializedData.Phone != null ? new CipherString(deserializedData.Phone) : null;
|
||||
SSN = deserializedData.SSN != null ? new CipherString(deserializedData.SSN) : null;
|
||||
Username = deserializedData.Username != null ? new CipherString(deserializedData.Username) : null;
|
||||
PassportNumber = deserializedData.PassportNumber != null ?
|
||||
new CipherString(deserializedData.PassportNumber) : null;
|
||||
LicenseNumber = deserializedData.LicenseNumber != null ?
|
||||
new CipherString(deserializedData.LicenseNumber) : null;
|
||||
}
|
||||
|
||||
public CipherString Title { get; set; }
|
||||
public CipherString FirstName { get; set; }
|
||||
public CipherString MiddleName { get; set; }
|
||||
public CipherString LastName { get; set; }
|
||||
public CipherString Address1 { get; set; }
|
||||
public CipherString Address2 { get; set; }
|
||||
public CipherString Address3 { get; set; }
|
||||
public CipherString City { get; set; }
|
||||
public CipherString State { get; set; }
|
||||
public CipherString PostalCode { get; set; }
|
||||
public CipherString Country { get; set; }
|
||||
public CipherString Company { get; set; }
|
||||
public CipherString Email { get; set; }
|
||||
public CipherString Phone { get; set; }
|
||||
public CipherString SSN { get; set; }
|
||||
public CipherString Username { get; set; }
|
||||
public CipherString PassportNumber { get; set; }
|
||||
public CipherString LicenseNumber { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,58 +1,22 @@
|
||||
using Bit.App.Models.Api;
|
||||
using Bit.App.Models.Data;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Bit.App.Models.Data;
|
||||
|
||||
namespace Bit.App.Models
|
||||
{
|
||||
public class Login
|
||||
{
|
||||
public Login()
|
||||
{ }
|
||||
public Login() { }
|
||||
|
||||
public Login(LoginData data, IEnumerable<AttachmentData> attachments = null)
|
||||
public Login(CipherData data)
|
||||
{
|
||||
Id = data.Id;
|
||||
UserId = data.UserId;
|
||||
OrganizationId = data.OrganizationId;
|
||||
FolderId = data.FolderId;
|
||||
Name = data.Name != null ? new CipherString(data.Name) : null;
|
||||
Uri = data.Uri != null ? new CipherString(data.Uri) : null;
|
||||
Username = data.Username != null ? new CipherString(data.Username) : null;
|
||||
Password = data.Password != null ? new CipherString(data.Password) : null;
|
||||
Notes = data.Notes != null ? new CipherString(data.Notes) : null;
|
||||
Totp = data.Totp != null ? new CipherString(data.Totp) : null;
|
||||
Favorite = data.Favorite;
|
||||
Edit = data.Edit;
|
||||
OrganizationUseTotp = data.OrganizationUseTotp;
|
||||
Attachments = attachments?.Select(a => new Attachment(a));
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(data.Fields))
|
||||
{
|
||||
try
|
||||
{
|
||||
var fieldModels = JsonConvert.DeserializeObject<IEnumerable<FieldDataModel>>(data.Fields);
|
||||
Fields = fieldModels?.Select(f => new Field(f));
|
||||
}
|
||||
catch(JsonSerializationException) { }
|
||||
}
|
||||
}
|
||||
|
||||
public string Id { get; set; }
|
||||
public string UserId { get; set; }
|
||||
public string OrganizationId { get; set; }
|
||||
public string FolderId { get; set; }
|
||||
public CipherString Name { get; set; }
|
||||
public CipherString Uri { get; set; }
|
||||
public CipherString Username { get; set; }
|
||||
public CipherString Password { get; set; }
|
||||
public CipherString Notes { get; set; }
|
||||
public CipherString Totp { get; set; }
|
||||
public IEnumerable<Field> Fields { get; set; }
|
||||
public bool Favorite { get; set; }
|
||||
public bool Edit { get; set; }
|
||||
public bool OrganizationUseTotp { get; set; }
|
||||
public IEnumerable<Attachment> Attachments { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,24 +2,116 @@
|
||||
using System.Collections.Generic;
|
||||
using Bit.App.Resources;
|
||||
using System.Linq;
|
||||
using Bit.App.Enums;
|
||||
using Bit.App.Abstractions;
|
||||
|
||||
namespace Bit.App.Models.Page
|
||||
{
|
||||
public class VaultListPageModel
|
||||
{
|
||||
public class Login
|
||||
public class Cipher
|
||||
{
|
||||
public Login(Models.Login login)
|
||||
public Cipher(Models.Cipher cipher, IAppSettingsService appSettings)
|
||||
{
|
||||
Id = login.Id;
|
||||
Shared = !string.IsNullOrWhiteSpace(login.OrganizationId);
|
||||
HasAttachments = login.Attachments?.Any() ?? false;
|
||||
FolderId = login.FolderId;
|
||||
Name = login.Name?.Decrypt(login.OrganizationId);
|
||||
Username = login.Username?.Decrypt(login.OrganizationId) ?? " ";
|
||||
Password = new Lazy<string>(() => login.Password?.Decrypt(login.OrganizationId));
|
||||
Uri = new Lazy<string>(() => login.Uri?.Decrypt(login.OrganizationId));
|
||||
Totp = new Lazy<string>(() => login.Totp?.Decrypt(login.OrganizationId));
|
||||
Id = cipher.Id;
|
||||
Shared = !string.IsNullOrWhiteSpace(cipher.OrganizationId);
|
||||
HasAttachments = cipher.Attachments?.Any() ?? false;
|
||||
FolderId = cipher.FolderId;
|
||||
Name = cipher.Name?.Decrypt(cipher.OrganizationId);
|
||||
Type = cipher.Type;
|
||||
|
||||
switch(cipher.Type)
|
||||
{
|
||||
case CipherType.Login:
|
||||
LoginUsername = cipher.Login?.Username?.Decrypt(cipher.OrganizationId) ?? " ";
|
||||
LoginUri = cipher.Login?.Uri?.Decrypt(cipher.OrganizationId) ?? " ";
|
||||
LoginPassword = new Lazy<string>(() => cipher.Login?.Password?.Decrypt(cipher.OrganizationId));
|
||||
LoginTotp = new Lazy<string>(() => cipher.Login?.Totp?.Decrypt(cipher.OrganizationId));
|
||||
|
||||
Icon = "login.png";
|
||||
var hostnameUri = LoginUri;
|
||||
var isWebsite = false;
|
||||
var imageEnabled = !appSettings.DisableWebsiteIcons;
|
||||
if(hostnameUri.StartsWith("androidapp://"))
|
||||
{
|
||||
Icon = "android.png";
|
||||
}
|
||||
else if(hostnameUri.StartsWith("iosapp://"))
|
||||
{
|
||||
Icon = "apple.png";
|
||||
}
|
||||
else if(imageEnabled && !hostnameUri.Contains("://") && hostnameUri.Contains("."))
|
||||
{
|
||||
hostnameUri = $"http://{hostnameUri}";
|
||||
isWebsite = true;
|
||||
}
|
||||
else if(imageEnabled)
|
||||
{
|
||||
isWebsite = hostnameUri.StartsWith("http") && hostnameUri.Contains(".");
|
||||
}
|
||||
|
||||
if(imageEnabled && isWebsite && Uri.TryCreate(hostnameUri, UriKind.Absolute, out Uri u))
|
||||
{
|
||||
var iconsUrl = appSettings.IconsUrl;
|
||||
if(string.IsNullOrWhiteSpace(iconsUrl))
|
||||
{
|
||||
if(!string.IsNullOrWhiteSpace(appSettings.BaseUrl))
|
||||
{
|
||||
iconsUrl = $"{appSettings.BaseUrl}/icons";
|
||||
}
|
||||
else
|
||||
{
|
||||
iconsUrl = "https://icons.bitwarden.com";
|
||||
}
|
||||
}
|
||||
|
||||
Icon = $"{iconsUrl}/{u.Host}/icon.png";
|
||||
}
|
||||
|
||||
Subtitle = LoginUsername;
|
||||
break;
|
||||
case CipherType.SecureNote:
|
||||
Icon = "note.png";
|
||||
Subtitle = " ";
|
||||
break;
|
||||
case CipherType.Card:
|
||||
CardNumber = cipher.Card?.Number?.Decrypt(cipher.OrganizationId) ?? " ";
|
||||
var cardBrand = cipher.Card?.Brand?.Decrypt(cipher.OrganizationId) ?? " ";
|
||||
CardCode = new Lazy<string>(() => cipher.Card?.Code?.Decrypt(cipher.OrganizationId));
|
||||
|
||||
Icon = "card.png";
|
||||
Subtitle = cardBrand;
|
||||
if(!string.IsNullOrWhiteSpace(CardNumber) && CardNumber.Length >= 4)
|
||||
{
|
||||
if(!string.IsNullOrWhiteSpace(CardNumber))
|
||||
{
|
||||
Subtitle += ", ";
|
||||
}
|
||||
Subtitle += ("*" + CardNumber.Substring(CardNumber.Length - 4));
|
||||
}
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
var firstName = cipher.Identity?.FirstName?.Decrypt(cipher.OrganizationId) ?? " ";
|
||||
var lastName = cipher.Identity?.LastName?.Decrypt(cipher.OrganizationId) ?? " ";
|
||||
|
||||
Icon = "id.png";
|
||||
Subtitle = " ";
|
||||
if(!string.IsNullOrWhiteSpace(firstName))
|
||||
{
|
||||
Subtitle = firstName;
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(lastName))
|
||||
{
|
||||
if(!string.IsNullOrWhiteSpace(Subtitle))
|
||||
{
|
||||
Subtitle += " ";
|
||||
}
|
||||
Subtitle += lastName;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public string Id { get; set; }
|
||||
@@ -27,16 +119,26 @@ namespace Bit.App.Models.Page
|
||||
public bool HasAttachments { get; set; }
|
||||
public string FolderId { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Username { get; set; }
|
||||
public Lazy<string> Password { get; set; }
|
||||
public Lazy<string> Uri { get; set; }
|
||||
public Lazy<string> Totp { get; set; }
|
||||
public string Subtitle { get; set; }
|
||||
public CipherType Type { get; set; }
|
||||
public string Icon { get; set; }
|
||||
public string Image { get; set; }
|
||||
|
||||
// Login metadata
|
||||
public string LoginUsername { get; set; }
|
||||
public Lazy<string> LoginPassword { get; set; }
|
||||
public string LoginUri { get; set; }
|
||||
public Lazy<string> LoginTotp { get; set; }
|
||||
|
||||
// Login metadata
|
||||
public string CardNumber { get; set; }
|
||||
public Lazy<string> CardCode { get; set; }
|
||||
}
|
||||
|
||||
public class AutofillLogin : Login
|
||||
public class AutofillCipher : Cipher
|
||||
{
|
||||
public AutofillLogin(Models.Login login, bool fuzzy = false)
|
||||
: base(login)
|
||||
public AutofillCipher(Models.Cipher cipher, IAppSettingsService appSettings, bool fuzzy = false)
|
||||
: base(cipher, appSettings)
|
||||
{
|
||||
Fuzzy = fuzzy;
|
||||
}
|
||||
@@ -44,7 +146,7 @@ namespace Bit.App.Models.Page
|
||||
public bool Fuzzy { get; set; }
|
||||
}
|
||||
|
||||
public class Folder : List<Login>
|
||||
public class Folder : List<Cipher>
|
||||
{
|
||||
public Folder(Models.Folder folder)
|
||||
{
|
||||
@@ -52,18 +154,18 @@ namespace Bit.App.Models.Page
|
||||
Name = folder.Name?.Decrypt();
|
||||
}
|
||||
|
||||
public Folder(List<Login> logins)
|
||||
public Folder(List<Cipher> ciphers)
|
||||
{
|
||||
AddRange(logins);
|
||||
AddRange(ciphers);
|
||||
}
|
||||
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; } = AppResources.FolderNone;
|
||||
}
|
||||
|
||||
public class AutofillGrouping : List<AutofillLogin>
|
||||
public class AutofillGrouping : List<AutofillCipher>
|
||||
{
|
||||
public AutofillGrouping(List<AutofillLogin> logins, string name)
|
||||
public AutofillGrouping(List<AutofillCipher> logins, string name)
|
||||
{
|
||||
AddRange(logins);
|
||||
Name = name;
|
||||
|
||||
669
src/App/Models/Page/VaultViewCipherPageModel.cs
Normal file
@@ -0,0 +1,669 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Xamarin.Forms;
|
||||
using System.Collections.Generic;
|
||||
using Bit.App.Enums;
|
||||
|
||||
namespace Bit.App.Models.Page
|
||||
{
|
||||
public class VaultViewCipherPageModel : INotifyPropertyChanged
|
||||
{
|
||||
private string _name, _notes;
|
||||
private List<Attachment> _attachments;
|
||||
private List<Field> _fields;
|
||||
|
||||
// Login
|
||||
private string _loginUsername, _loginPassword, _loginUri, _loginTotpCode;
|
||||
private int _loginTotpSec = 30;
|
||||
private bool _loginRevealPassword;
|
||||
|
||||
// Card
|
||||
private string _cardName, _cardNumber, _cardBrand, _cardExpMonth, _cardExpYear, _cardCode;
|
||||
|
||||
// Identity
|
||||
private string _idFirstName, _idLastName, _idMiddleName, _idCompany, _idEmail, _idPhone, _idUsername,
|
||||
_idPassportNumber, _idLicenseNumber, _idSsn, _idAddress1, _idAddress2, _idAddress3, _idCity,
|
||||
_idState, _idCountry, _idPostalCode, _idTitle;
|
||||
|
||||
public VaultViewCipherPageModel() { }
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
_name = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Name)));
|
||||
}
|
||||
}
|
||||
|
||||
public string Notes
|
||||
{
|
||||
get => _notes;
|
||||
set
|
||||
{
|
||||
_notes = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Notes)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowNotes)));
|
||||
}
|
||||
}
|
||||
public bool ShowNotes => !string.IsNullOrWhiteSpace(Notes);
|
||||
|
||||
public List<Attachment> Attachments
|
||||
{
|
||||
get => _attachments;
|
||||
set
|
||||
{
|
||||
_attachments = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Attachments)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowAttachments)));
|
||||
}
|
||||
}
|
||||
public bool ShowAttachments => (Attachments?.Count ?? 0) > 0;
|
||||
|
||||
public List<Field> Fields
|
||||
{
|
||||
get => _fields;
|
||||
set
|
||||
{
|
||||
_fields = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Fields)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowFields)));
|
||||
}
|
||||
}
|
||||
public bool ShowFields => (Fields?.Count ?? 0) > 0;
|
||||
|
||||
// Login
|
||||
public string LoginUsername
|
||||
{
|
||||
get => _loginUsername;
|
||||
set
|
||||
{
|
||||
_loginUsername = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(LoginUsername)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowLoginUsername)));
|
||||
}
|
||||
}
|
||||
public bool ShowLoginUsername => !string.IsNullOrWhiteSpace(LoginUsername);
|
||||
|
||||
public string LoginPassword
|
||||
{
|
||||
get => _loginPassword;
|
||||
set
|
||||
{
|
||||
_loginPassword = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(LoginPassword)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(MaskedLoginPassword)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowLoginPassword)));
|
||||
}
|
||||
}
|
||||
public bool ShowLoginPassword => !string.IsNullOrWhiteSpace(LoginPassword);
|
||||
public bool RevealLoginPassword
|
||||
{
|
||||
get => _loginRevealPassword;
|
||||
set
|
||||
{
|
||||
_loginRevealPassword = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(RevealLoginPassword)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(MaskedLoginPassword)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(LoginShowHideImage)));
|
||||
}
|
||||
}
|
||||
public string MaskedLoginPassword => RevealLoginPassword ?
|
||||
LoginPassword : LoginPassword == null ? null : new string('●', LoginPassword.Length);
|
||||
public ImageSource LoginShowHideImage => RevealLoginPassword ?
|
||||
ImageSource.FromFile("eye_slash.png") : ImageSource.FromFile("eye.png");
|
||||
|
||||
public string LoginUri
|
||||
{
|
||||
get => _loginUri;
|
||||
set
|
||||
{
|
||||
_loginUri = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(LoginUri)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(LoginUriHost)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowLoginUri)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowLoginLaunch)));
|
||||
}
|
||||
}
|
||||
public bool ShowLoginUri => !string.IsNullOrWhiteSpace(LoginUri);
|
||||
public bool ShowLoginLaunch
|
||||
{
|
||||
get
|
||||
{
|
||||
if(!ShowLoginUri)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android && !LoginUri.StartsWith("http") &&
|
||||
!LoginUri.StartsWith("androidapp://"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(Device.RuntimePlatform != Device.Android && !LoginUri.StartsWith("http"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!Uri.TryCreate(LoginUri, UriKind.Absolute, out Uri uri))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public string LoginUriHost
|
||||
{
|
||||
get
|
||||
{
|
||||
if(!ShowLoginUri)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if(!Uri.TryCreate(LoginUri, UriKind.Absolute, out Uri uri))
|
||||
{
|
||||
return LoginUri;
|
||||
}
|
||||
|
||||
if(DomainName.TryParseBaseDomain(uri.Host, out string domain))
|
||||
{
|
||||
return domain;
|
||||
}
|
||||
|
||||
return uri.Host;
|
||||
}
|
||||
}
|
||||
|
||||
public string LoginTotpCode
|
||||
{
|
||||
get => _loginTotpCode;
|
||||
set
|
||||
{
|
||||
_loginTotpCode = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(LoginTotpCode)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(LoginTotpCodeFormatted)));
|
||||
}
|
||||
}
|
||||
public int LoginTotpSecond
|
||||
{
|
||||
get => _loginTotpSec;
|
||||
set
|
||||
{
|
||||
_loginTotpSec = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(LoginTotpSecond)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(LoginTotpColor)));
|
||||
}
|
||||
}
|
||||
public bool LoginTotpLow => LoginTotpSecond <= 7;
|
||||
public Color LoginTotpColor => !string.IsNullOrWhiteSpace(LoginTotpCode) && LoginTotpLow ?
|
||||
Color.Red : Color.Black;
|
||||
public string LoginTotpCodeFormatted => !string.IsNullOrWhiteSpace(LoginTotpCode) ?
|
||||
string.Format("{0} {1}", LoginTotpCode.Substring(0, 3), LoginTotpCode.Substring(3)) : null;
|
||||
|
||||
// Card
|
||||
public string CardName
|
||||
{
|
||||
get => _cardName;
|
||||
set
|
||||
{
|
||||
_cardName = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(CardName)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowCardName)));
|
||||
}
|
||||
}
|
||||
public bool ShowCardName => !string.IsNullOrWhiteSpace(CardName);
|
||||
|
||||
public string CardNumber
|
||||
{
|
||||
get => _cardNumber;
|
||||
set
|
||||
{
|
||||
_cardNumber = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(CardNumber)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowCardNumber)));
|
||||
}
|
||||
}
|
||||
public bool ShowCardNumber => !string.IsNullOrWhiteSpace(CardNumber);
|
||||
|
||||
public string CardBrand
|
||||
{
|
||||
get => _cardBrand;
|
||||
set
|
||||
{
|
||||
_cardBrand = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(CardBrand)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowCardBrand)));
|
||||
}
|
||||
}
|
||||
public bool ShowCardBrand => !string.IsNullOrWhiteSpace(CardBrand);
|
||||
|
||||
public string CardExpMonth
|
||||
{
|
||||
private get => _cardExpMonth;
|
||||
set
|
||||
{
|
||||
_cardExpMonth = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(CardExpMonth)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(CardExp)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowCardExp)));
|
||||
}
|
||||
}
|
||||
|
||||
public string CardExpYear
|
||||
{
|
||||
private get => _cardExpYear;
|
||||
set
|
||||
{
|
||||
_cardExpYear = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(CardExpYear)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(CardExp)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowCardExp)));
|
||||
}
|
||||
}
|
||||
|
||||
public string CardExp
|
||||
{
|
||||
get
|
||||
{
|
||||
var expMonth = !string.IsNullOrWhiteSpace(CardExpMonth) ? CardExpMonth.PadLeft(2, '0') : "__";
|
||||
var expYear = "____";
|
||||
if(!string.IsNullOrWhiteSpace(CardExpYear))
|
||||
{
|
||||
expYear = CardExpYear;
|
||||
}
|
||||
if(expYear.Length == 2)
|
||||
{
|
||||
expYear = "20" + expYear;
|
||||
}
|
||||
|
||||
return $"{expMonth} / {expYear}";
|
||||
}
|
||||
}
|
||||
public bool ShowCardExp => !string.IsNullOrWhiteSpace(CardExpMonth) && !string.IsNullOrWhiteSpace(CardExpYear);
|
||||
|
||||
public string CardCode
|
||||
{
|
||||
get => _cardCode;
|
||||
set
|
||||
{
|
||||
_cardCode = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(CardCode)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowCardCode)));
|
||||
}
|
||||
}
|
||||
public bool ShowCardCode => !string.IsNullOrWhiteSpace(CardCode);
|
||||
|
||||
// Identity
|
||||
|
||||
public string IdTitle
|
||||
{
|
||||
get => _idTitle;
|
||||
set
|
||||
{
|
||||
_idTitle = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdTitle)));
|
||||
}
|
||||
}
|
||||
public string IdFirstName
|
||||
{
|
||||
private get => _idFirstName;
|
||||
set
|
||||
{
|
||||
_idFirstName = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdFirstName)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowIdName)));
|
||||
}
|
||||
}
|
||||
public string IdMiddleName
|
||||
{
|
||||
private get => _idMiddleName;
|
||||
set
|
||||
{
|
||||
_idMiddleName = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdMiddleName)));
|
||||
}
|
||||
}
|
||||
public string IdLastName
|
||||
{
|
||||
private get => _idLastName;
|
||||
set
|
||||
{
|
||||
_idLastName = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdLastName)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowIdName)));
|
||||
}
|
||||
}
|
||||
public string IdName
|
||||
{
|
||||
get
|
||||
{
|
||||
var name = IdTitle;
|
||||
if(!string.IsNullOrWhiteSpace(IdFirstName))
|
||||
{
|
||||
name += ((!string.IsNullOrWhiteSpace(name) ? " " : string.Empty) + IdFirstName);
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(IdMiddleName))
|
||||
{
|
||||
name += ((!string.IsNullOrWhiteSpace(name) ? " " : string.Empty) + IdMiddleName);
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(IdLastName))
|
||||
{
|
||||
name += ((!string.IsNullOrWhiteSpace(name) ? " " : string.Empty) + IdLastName);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
public bool ShowIdName => !string.IsNullOrWhiteSpace(IdFirstName) || !string.IsNullOrWhiteSpace(IdLastName);
|
||||
|
||||
public string IdUsername
|
||||
{
|
||||
get => _idUsername;
|
||||
set
|
||||
{
|
||||
_idUsername = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdUsername)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowIdUsername)));
|
||||
}
|
||||
}
|
||||
public bool ShowIdUsername => !string.IsNullOrWhiteSpace(IdUsername);
|
||||
|
||||
public string IdCompany
|
||||
{
|
||||
get => _idCompany;
|
||||
set
|
||||
{
|
||||
_idCompany = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdCompany)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowIdCompany)));
|
||||
}
|
||||
}
|
||||
public bool ShowIdCompany => !string.IsNullOrWhiteSpace(IdCompany);
|
||||
|
||||
public string IdSsn
|
||||
{
|
||||
get => _idSsn;
|
||||
set
|
||||
{
|
||||
_idSsn = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdSsn)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowIdSsn)));
|
||||
}
|
||||
}
|
||||
public bool ShowIdSsn => !string.IsNullOrWhiteSpace(IdSsn);
|
||||
|
||||
public string IdPassportNumber
|
||||
{
|
||||
get => _idPassportNumber;
|
||||
set
|
||||
{
|
||||
_idPassportNumber = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdPassportNumber)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowIdPassportNumber)));
|
||||
}
|
||||
}
|
||||
public bool ShowIdPassportNumber => !string.IsNullOrWhiteSpace(IdPassportNumber);
|
||||
|
||||
public string IdLicenseNumber
|
||||
{
|
||||
get => _idLicenseNumber;
|
||||
set
|
||||
{
|
||||
_idLicenseNumber = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdLicenseNumber)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowIdLicenseNumber)));
|
||||
}
|
||||
}
|
||||
public bool ShowIdLicenseNumber => !string.IsNullOrWhiteSpace(IdLicenseNumber);
|
||||
|
||||
public string IdEmail
|
||||
{
|
||||
get => _idEmail;
|
||||
set
|
||||
{
|
||||
_idEmail = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdEmail)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowIdEmail)));
|
||||
}
|
||||
}
|
||||
public bool ShowIdEmail => !string.IsNullOrWhiteSpace(IdEmail);
|
||||
|
||||
public string IdPhone
|
||||
{
|
||||
get => _idPhone;
|
||||
set
|
||||
{
|
||||
_idPhone = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdPhone)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowIdPhone)));
|
||||
}
|
||||
}
|
||||
public bool ShowIdPhone => !string.IsNullOrWhiteSpace(IdPhone);
|
||||
|
||||
public string IdAddress1
|
||||
{
|
||||
get => _idAddress1;
|
||||
set
|
||||
{
|
||||
_idAddress1 = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdAddress1)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdAddress)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowIdAddress)));
|
||||
}
|
||||
}
|
||||
public string IdAddress2
|
||||
{
|
||||
get => _idAddress2;
|
||||
set
|
||||
{
|
||||
_idAddress2 = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdAddress2)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdAddress)));
|
||||
}
|
||||
}
|
||||
public string IdAddress3
|
||||
{
|
||||
get => _idAddress3;
|
||||
set
|
||||
{
|
||||
_idAddress3 = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdAddress3)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdAddress)));
|
||||
}
|
||||
}
|
||||
public string IdCity
|
||||
{
|
||||
get => _idCity;
|
||||
set
|
||||
{
|
||||
_idCity = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdCity)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdAddress)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowIdAddress)));
|
||||
}
|
||||
}
|
||||
public string IdState
|
||||
{
|
||||
get => _idState;
|
||||
set
|
||||
{
|
||||
_idState = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdState)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdAddress)));
|
||||
}
|
||||
}
|
||||
public string IdPostalCode
|
||||
{
|
||||
get => _idPostalCode;
|
||||
set
|
||||
{
|
||||
_idPostalCode = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdPostalCode)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdAddress)));
|
||||
}
|
||||
}
|
||||
public string IdCountry
|
||||
{
|
||||
get => _idCountry;
|
||||
set
|
||||
{
|
||||
_idCountry = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdCountry)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(IdAddress)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowIdAddress)));
|
||||
}
|
||||
}
|
||||
public string IdAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
var address = IdAddress1;
|
||||
if(!string.IsNullOrWhiteSpace(IdAddress2))
|
||||
{
|
||||
address += ((!string.IsNullOrWhiteSpace(address) ? "\n" : string.Empty) + IdAddress2);
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(IdAddress3))
|
||||
{
|
||||
address += ((!string.IsNullOrWhiteSpace(address) ? "\n" : string.Empty) + IdAddress3);
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(IdCity) || !string.IsNullOrWhiteSpace(IdState) ||
|
||||
!string.IsNullOrWhiteSpace(IdPostalCode))
|
||||
{
|
||||
var cityLine = IdCity + ", ";
|
||||
cityLine += !string.IsNullOrWhiteSpace(IdState) ? IdState : "-";
|
||||
cityLine += " ";
|
||||
cityLine += !string.IsNullOrWhiteSpace(IdPostalCode) ? IdPostalCode : "-";
|
||||
address += ((!string.IsNullOrWhiteSpace(address) ? "\n" : string.Empty) + cityLine);
|
||||
}
|
||||
if(!string.IsNullOrWhiteSpace(IdCountry))
|
||||
{
|
||||
address += ((!string.IsNullOrWhiteSpace(address) ? "\n" : string.Empty) + IdCountry);
|
||||
}
|
||||
return address;
|
||||
}
|
||||
}
|
||||
public bool ShowIdAddress => !string.IsNullOrWhiteSpace(IdAddress1) || !string.IsNullOrWhiteSpace(IdCity) ||
|
||||
!string.IsNullOrWhiteSpace(IdCountry);
|
||||
|
||||
public void Update(Cipher cipher)
|
||||
{
|
||||
Name = cipher.Name?.Decrypt(cipher.OrganizationId);
|
||||
Notes = cipher.Notes?.Decrypt(cipher.OrganizationId);
|
||||
|
||||
if(cipher.Attachments != null)
|
||||
{
|
||||
var attachments = new List<Attachment>();
|
||||
foreach(var attachment in cipher.Attachments)
|
||||
{
|
||||
attachments.Add(new Attachment
|
||||
{
|
||||
Id = attachment.Id,
|
||||
Name = attachment.FileName?.Decrypt(cipher.OrganizationId),
|
||||
SizeName = attachment.SizeName,
|
||||
Size = attachment.Size,
|
||||
Url = attachment.Url
|
||||
});
|
||||
}
|
||||
Attachments = attachments;
|
||||
}
|
||||
else
|
||||
{
|
||||
cipher.Attachments = null;
|
||||
}
|
||||
|
||||
if(cipher.Fields != null)
|
||||
{
|
||||
var fields = new List<Field>();
|
||||
foreach(var field in cipher.Fields)
|
||||
{
|
||||
fields.Add(new Field
|
||||
{
|
||||
Name = field.Name?.Decrypt(cipher.OrganizationId),
|
||||
Value = field.Value?.Decrypt(cipher.OrganizationId),
|
||||
Type = field.Type
|
||||
});
|
||||
}
|
||||
Fields = fields;
|
||||
}
|
||||
else
|
||||
{
|
||||
cipher.Fields = null;
|
||||
}
|
||||
|
||||
switch(cipher.Type)
|
||||
{
|
||||
case CipherType.Login:
|
||||
LoginUsername = cipher.Login.Username?.Decrypt(cipher.OrganizationId);
|
||||
LoginPassword = cipher.Login.Password?.Decrypt(cipher.OrganizationId);
|
||||
LoginUri = cipher.Login.Uri?.Decrypt(cipher.OrganizationId);
|
||||
break;
|
||||
case CipherType.Card:
|
||||
CardName = cipher.Card.CardholderName?.Decrypt(cipher.OrganizationId);
|
||||
CardNumber = cipher.Card.Number?.Decrypt(cipher.OrganizationId);
|
||||
CardBrand = cipher.Card.Brand?.Decrypt(cipher.OrganizationId);
|
||||
CardExpMonth = cipher.Card.ExpMonth?.Decrypt(cipher.OrganizationId);
|
||||
CardExpYear = cipher.Card.ExpYear?.Decrypt(cipher.OrganizationId);
|
||||
CardCode = cipher.Card.Code?.Decrypt(cipher.OrganizationId);
|
||||
break;
|
||||
case CipherType.Identity:
|
||||
IdTitle = cipher.Identity.Title?.Decrypt(cipher.OrganizationId);
|
||||
IdFirstName = cipher.Identity.FirstName?.Decrypt(cipher.OrganizationId);
|
||||
IdMiddleName = cipher.Identity.MiddleName?.Decrypt(cipher.OrganizationId);
|
||||
IdLastName = cipher.Identity.LastName?.Decrypt(cipher.OrganizationId);
|
||||
IdCompany = cipher.Identity.Company?.Decrypt(cipher.OrganizationId);
|
||||
IdUsername = cipher.Identity.Username?.Decrypt(cipher.OrganizationId);
|
||||
IdSsn = cipher.Identity.SSN?.Decrypt(cipher.OrganizationId);
|
||||
IdPassportNumber = cipher.Identity.PassportNumber?.Decrypt(cipher.OrganizationId);
|
||||
IdLicenseNumber = cipher.Identity.LicenseNumber?.Decrypt(cipher.OrganizationId);
|
||||
IdEmail = cipher.Identity.Email?.Decrypt(cipher.OrganizationId);
|
||||
IdPhone = cipher.Identity.Phone?.Decrypt(cipher.OrganizationId);
|
||||
IdAddress1 = cipher.Identity.Address1?.Decrypt(cipher.OrganizationId);
|
||||
IdAddress2 = cipher.Identity.Address2?.Decrypt(cipher.OrganizationId);
|
||||
IdAddress3 = cipher.Identity.Address3?.Decrypt(cipher.OrganizationId);
|
||||
IdCity = cipher.Identity.City?.Decrypt(cipher.OrganizationId);
|
||||
IdState = cipher.Identity.State?.Decrypt(cipher.OrganizationId);
|
||||
IdPostalCode = cipher.Identity.PostalCode?.Decrypt(cipher.OrganizationId);
|
||||
IdCountry = cipher.Identity.Country?.Decrypt(cipher.OrganizationId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public class Attachment
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string SizeName { get; set; }
|
||||
public long Size { get; set; }
|
||||
public string Url { get; set; }
|
||||
}
|
||||
|
||||
public class Field
|
||||
{
|
||||
private string _maskedValue;
|
||||
|
||||
public string Name { get; set; }
|
||||
public string Value { get; set; }
|
||||
public string MaskedValue
|
||||
{
|
||||
get
|
||||
{
|
||||
if(_maskedValue == null && Value != null)
|
||||
{
|
||||
_maskedValue = new string('●', Value.Length);
|
||||
}
|
||||
|
||||
return _maskedValue;
|
||||
}
|
||||
}
|
||||
public FieldType Type { get; set; }
|
||||
public bool Revealed { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||