Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5350e5385c | ||
|
|
8f18c4fd45 | ||
|
|
8538fbabe5 | ||
|
|
9367b34bbe | ||
|
|
a766044cb4 | ||
|
|
0eb385e49f | ||
|
|
e30136dace | ||
|
|
c50dee479a | ||
|
|
58ef292fa7 | ||
|
|
61b728fea7 | ||
|
|
b782eeb839 | ||
|
|
77314d4b8d | ||
|
|
c79d1d24b3 | ||
|
|
5dbea8ca09 | ||
|
|
09a1c17fb4 | ||
|
|
a0632bcac2 | ||
|
|
07d57ebe8c | ||
|
|
325c88018c | ||
|
|
dcb1102746 | ||
|
|
636d3c02c4 | ||
|
|
5b119ded17 | ||
|
|
f25ae870c5 | ||
|
|
49673262e4 | ||
|
|
3ed814c1f7 | ||
|
|
8b858e5407 | ||
|
|
30145894b6 | ||
|
|
8df4c27203 |
@@ -8,7 +8,7 @@
|
||||
|
||||
The Bitwarden mobile application is written in C# with Xamarin Android, Xamarin iOS, and Xamarin Forms.
|
||||
|
||||
<img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-android.png" alt="" width="300" height="533" /> <img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-ios.png" alt="" width="300" height="533" />
|
||||
<img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-android-myvault.png" alt="" width="300" height="533" /> <img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/mobile-ios.png" alt="" width="300" height="533" />
|
||||
|
||||
# Build/Run
|
||||
|
||||
|
||||
@@ -33,10 +33,10 @@
|
||||
<AndroidEnableMultiDex>true</AndroidEnableMultiDex>
|
||||
<AndroidSupportedAbis />
|
||||
<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
|
||||
<AndroidLinkSkip>Xamarin.GooglePlayServices.Base;Xamarin.GooglePlayServices.Basement;Xamarin.GooglePlayServices.Measurement;Xamarin.GooglePlayServices.Gcm;BitwardenAndroid;BitwardenApp;Xamarin.Android.Net</AndroidLinkSkip>
|
||||
<AndroidLinkSkip>Xamarin.GooglePlayServices.Base;Xamarin.GooglePlayServices.Basement;Xamarin.GooglePlayServices.Measurement;Xamarin.GooglePlayServices.Gcm;BitwardenAndroid;BitwardenApp;BitwardenCore;Xamarin.Android.Net</AndroidLinkSkip>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release</OutputPath>
|
||||
@@ -44,13 +44,15 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidManagedSymbols>true</AndroidManagedSymbols>
|
||||
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
|
||||
<AndroidSupportedAbis />
|
||||
<AndroidSupportedAbis>armeabi-v7a;x86;x86_64;arm64-v8a</AndroidSupportedAbis>
|
||||
<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
|
||||
<AndroidEnableMultiDex>true</AndroidEnableMultiDex>
|
||||
<AndroidLinkSkip>Xamarin.GooglePlayServices.Base;Xamarin.GooglePlayServices.Basement;Xamarin.GooglePlayServices.Measurement;Xamarin.GooglePlayServices.Gcm;BitwardenAndroid;BitwardenApp;Xamarin.Android.Net</AndroidLinkSkip>
|
||||
<AndroidLinkSkip>Xamarin.GooglePlayServices.Base;Xamarin.GooglePlayServices.Basement;Xamarin.GooglePlayServices.Measurement;Xamarin.GooglePlayServices.Gcm;BitwardenAndroid;BitwardenApp;BitwardenCore;Xamarin.Android.Net</AndroidLinkSkip>
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
<AndroidLinkMode>Full</AndroidLinkMode>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'FDroid|AnyCPU'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<OutputPath>bin\FDroid\</OutputPath>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@@ -59,18 +61,20 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<DefineConstants>FDROID</DefineConstants>
|
||||
<AndroidSupportedAbis />
|
||||
<AndroidSupportedAbis>armeabi-v7a;x86;x86_64;arm64-v8a</AndroidSupportedAbis>
|
||||
<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>
|
||||
<AndroidEnableMultiDex>true</AndroidEnableMultiDex>
|
||||
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
<AndroidLinkSkip>Xamarin.GooglePlayServices.Base;Xamarin.GooglePlayServices.Basement;Xamarin.GooglePlayServices.Measurement;Xamarin.GooglePlayServices.Gcm;BitwardenAndroid;BitwardenApp;Xamarin.Android.Net</AndroidLinkSkip>
|
||||
<AndroidLinkSkip>Xamarin.GooglePlayServices.Base;Xamarin.GooglePlayServices.Basement;Xamarin.GooglePlayServices.Measurement;Xamarin.GooglePlayServices.Gcm;BitwardenAndroid;BitwardenApp;BitwardenCore;Xamarin.Android.Net</AndroidLinkSkip>
|
||||
<AndroidLinkMode>Full</AndroidLinkMode>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Android" />
|
||||
<Reference Include="Mono.Android.Export" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -66,7 +66,6 @@ namespace Bit.Droid.Autofill
|
||||
"androidapp://android",
|
||||
"androidapp://com.x8bit.bitwarden",
|
||||
"androidapp://com.oneplus.applocker",
|
||||
"androidapp://com.android.settings",
|
||||
};
|
||||
|
||||
public static async Task<List<FilledItem>> GetFillItemsAsync(Parser parser, ICipherService cipherService)
|
||||
|
||||
@@ -15,6 +15,7 @@ using Bit.Droid.Services;
|
||||
using Bit.Droid.Utilities;
|
||||
using Plugin.CurrentActivity;
|
||||
using Plugin.Fingerprint;
|
||||
using Xamarin.Android.Net;
|
||||
#if !FDROID
|
||||
using Android.Gms.Security;
|
||||
#endif
|
||||
@@ -39,7 +40,7 @@ namespace Bit.Droid
|
||||
if(ServiceContainer.RegisteredServices.Count == 0)
|
||||
{
|
||||
RegisterLocalServices();
|
||||
ServiceContainer.Init();
|
||||
ServiceContainer.Init(new AndroidClientHandler());
|
||||
if(App.Migration.MigrationHelpers.NeedsMigration())
|
||||
{
|
||||
var task = App.Migration.MigrationHelpers.PerformMigrationAsync();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:versionCode="1"
|
||||
android:versionName="2.0.1"
|
||||
android:versionName="2.0.6"
|
||||
package="com.x8bit.bitwarden">
|
||||
|
||||
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="28" />
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
<item name="colorPrimary">@android:color/black</item>
|
||||
<item name="colorPrimaryDark">@android:color/black</item>
|
||||
<item name="colorControlNormal">@color/black_border</item>
|
||||
<item name="android:navigationBarColor">@android:color/black</item>
|
||||
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
<!-- Nord theme -->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<network-security-config>
|
||||
<base-config>
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<!-- Trust pre-installed CAs -->
|
||||
<certificates src="system" />
|
||||
|
||||
@@ -54,6 +54,11 @@ namespace Bit.Droid.Services
|
||||
netLanguage = "zh-Hans";
|
||||
}
|
||||
}
|
||||
else if(androidLanguage.StartsWith("iw"))
|
||||
{
|
||||
// Uncomment when we support RTL
|
||||
// netLanguage = "he";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Certain languages need to be converted to CultureInfo equivalent
|
||||
|
||||
@@ -13,19 +13,20 @@
|
||||
<pages:TwoFactorPageViewModel />
|
||||
</ContentPage.BindingContext>
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="{u:I18n Cancel}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
|
||||
x:Name="_cancelItem" />
|
||||
<ToolbarItem Text="{u:I18n Continue}" Clicked="Continue_Clicked" Order="Primary"
|
||||
x:Name="_continueItem" />
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<u:InverseBoolConverter x:Key="inverseBool" />
|
||||
<u:IsNullConverter x:Key="isNull" />
|
||||
<ToolbarItem Text="{u:I18n Continue}" Clicked="Continue_Clicked"
|
||||
x:Name="_continueItem" x:Key="continueItem" />
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="{u:I18n Cancel}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ScrollView x:Name="_scrollView">
|
||||
<StackLayout Spacing="10" Padding="0, 0, 0, 10" VerticalOptions="FillAndExpand">
|
||||
<StackLayout Spacing="20" Padding="0" IsVisible="{Binding TotpMethod, Mode=OneWay}">
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Bit.App.Pages
|
||||
DuoWebView = _duoWebView;
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
ToolbarItems.RemoveAt(0);
|
||||
ToolbarItems.Remove(_cancelItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Bit.App.Pages
|
||||
|
||||
public void AddContinueButton()
|
||||
{
|
||||
if(ToolbarItems.Count == 0)
|
||||
if(!ToolbarItems.Contains(_continueItem))
|
||||
{
|
||||
ToolbarItems.Add(_continueItem);
|
||||
}
|
||||
@@ -42,7 +42,7 @@ namespace Bit.App.Pages
|
||||
|
||||
public void RemoveContinueButton()
|
||||
{
|
||||
if(ToolbarItems.Count > 0)
|
||||
if(ToolbarItems.Contains(_continueItem))
|
||||
{
|
||||
ToolbarItems.Remove(_continueItem);
|
||||
}
|
||||
|
||||
@@ -19,17 +19,22 @@
|
||||
<ResourceDictionary>
|
||||
<u:InverseBoolConverter x:Key="inverseBool" />
|
||||
<u:DateTimeConverter x:Key="dateTime" />
|
||||
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
|
||||
x:Name="_closeItem" x:Key="closeItem" />
|
||||
<ToolbarItem Text="{u:I18n Clear}"
|
||||
Clicked="Clear_Clicked"
|
||||
Order="Secondary"
|
||||
x:Name="_clearItem"
|
||||
x:Key="clearItem" />
|
||||
<ToolbarItem Icon="more_vert.png"
|
||||
AutomationProperties.IsInAccessibleTree="True"
|
||||
AutomationProperties.Name="{u:I18n Options}"
|
||||
Clicked="More_Clicked"
|
||||
x:Name="_moreItem"
|
||||
x:Key="moreItem" />
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
|
||||
<ToolbarItem Text="{u:I18n Clear}"
|
||||
Clicked="Clear_Clicked"
|
||||
Order="Secondary"
|
||||
x:Name="_clearItem" />
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<StackLayout x:Name="_mainLayout">
|
||||
<Label IsVisible="{Binding ShowNoData}"
|
||||
Text="{u:I18n NoPasswordsToList}"
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using Bit.App.Resources;
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -12,6 +14,15 @@ namespace Bit.App.Pages
|
||||
SetActivityIndicator();
|
||||
_vm = BindingContext as GeneratorHistoryPageViewModel;
|
||||
_vm.Page = this;
|
||||
if(Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
ToolbarItems.Add(_closeItem);
|
||||
ToolbarItems.Add(_moreItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
ToolbarItems.Add(_clearItem);
|
||||
}
|
||||
}
|
||||
|
||||
protected override async void OnAppearing()
|
||||
@@ -34,5 +45,19 @@ namespace Bit.App.Pages
|
||||
await Navigation.PopModalAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private async void More_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if(!DoOnce())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var selection = await DisplayActionSheet(AppResources.Options, AppResources.Cancel,
|
||||
null, AppResources.Clear);
|
||||
if(selection == AppResources.Clear)
|
||||
{
|
||||
await _vm.ClearAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,19 +12,25 @@
|
||||
<pages:GeneratorPageViewModel />
|
||||
</ContentPage.BindingContext>
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="{u:I18n Select}"
|
||||
Clicked="Select_Clicked"
|
||||
Order="Primary"
|
||||
x:Name="_selectItem" />
|
||||
<ToolbarItem Text="{u:I18n PasswordHistory}"
|
||||
Clicked="History_Clicked"
|
||||
Order="Secondary" />
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<u:InverseBoolConverter x:Key="inverseBool" />
|
||||
<ToolbarItem Text="{u:I18n Select}"
|
||||
Clicked="Select_Clicked"
|
||||
Order="Primary"
|
||||
x:Name="_selectItem"
|
||||
x:Key="selectItem" />
|
||||
<ToolbarItem Text="{u:I18n PasswordHistory}"
|
||||
Clicked="History_Clicked"
|
||||
Order="Secondary"
|
||||
x:Name="_historyItem"
|
||||
x:Key="historyItem" />
|
||||
<ToolbarItem Icon="more_vert.png"
|
||||
AutomationProperties.IsInAccessibleTree="True"
|
||||
AutomationProperties.Name="{u:I18n Options}"
|
||||
Clicked="More_Clicked"
|
||||
x:Name="_moreItem"
|
||||
x:Key="moreItem" />
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Bit.App.Resources;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
@@ -19,9 +20,17 @@ namespace Bit.App.Pages
|
||||
_vm.Page = this;
|
||||
_fromTabPage = fromTabPage;
|
||||
_selectAction = selectAction;
|
||||
if(selectAction == null)
|
||||
if(selectAction != null)
|
||||
{
|
||||
ToolbarItems.Remove(_selectItem);
|
||||
ToolbarItems.Add(_selectItem);
|
||||
}
|
||||
if(Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
ToolbarItems.Add(_moreItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
ToolbarItems.Add(_historyItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +68,21 @@ namespace Bit.App.Pages
|
||||
await _vm.CopyAsync();
|
||||
}
|
||||
|
||||
private async void More_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if(!DoOnce())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var selection = await DisplayActionSheet(AppResources.Options, AppResources.Cancel,
|
||||
null, AppResources.PasswordHistory);
|
||||
if(selection == AppResources.PasswordHistory)
|
||||
{
|
||||
var page = new GeneratorHistoryPage();
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
}
|
||||
|
||||
private void Select_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
_selectAction?.Invoke(_vm.Password);
|
||||
|
||||
@@ -46,7 +46,10 @@ namespace Bit.App.Pages
|
||||
if(EditMode)
|
||||
{
|
||||
var folder = await _folderService.GetAsync(FolderId);
|
||||
Folder = await folder.DecryptAsync();
|
||||
if(folder != null)
|
||||
{
|
||||
Folder = await folder.DecryptAsync();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -57,6 +60,10 @@ namespace Bit.App.Pages
|
||||
|
||||
public async Task<bool> SubmitAsync()
|
||||
{
|
||||
if(Folder == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.None)
|
||||
{
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.InternetConnectionRequiredMessage,
|
||||
@@ -93,6 +100,10 @@ namespace Bit.App.Pages
|
||||
|
||||
public async Task<bool> DeleteAsync()
|
||||
{
|
||||
if(Folder == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.None)
|
||||
{
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.InternetConnectionRequiredMessage,
|
||||
|
||||
@@ -16,13 +16,15 @@
|
||||
<pages:FoldersPageViewModel />
|
||||
</ContentPage.BindingContext>
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<u:InverseBoolConverter x:Key="inverseBool" />
|
||||
<ToolbarItem x:Name="_closeItem" x:Key="closeItem" Text="{u:I18n Close}"
|
||||
Clicked="Close_Clicked" Order="Primary" Priority="-1" />
|
||||
<ToolbarItem x:Name="_addItem" x:Key="addItem" Icon="plus.png"
|
||||
Clicked="AddButton_Clicked" Order="Primary"
|
||||
AutomationProperties.IsInAccessibleTree="True"
|
||||
AutomationProperties.Name="{u:I18n AddItem}" />
|
||||
<StackLayout x:Name="_mainLayout" x:Key="mainLayout">
|
||||
<Label IsVisible="{Binding ShowNoData}"
|
||||
Text="{u:I18n NoFoldersToList}"
|
||||
@@ -68,7 +70,9 @@
|
||||
x:Name="_fab"
|
||||
ImageName="plus.png"
|
||||
AbsoluteLayout.LayoutFlags="PositionProportional"
|
||||
AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize">
|
||||
AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize"
|
||||
AutomationProperties.IsInAccessibleTree="True"
|
||||
AutomationProperties.Name="{u:I18n AddFolder}">
|
||||
</fab:FloatingActionButtonView>
|
||||
</AbsoluteLayout>
|
||||
|
||||
|
||||
@@ -18,10 +18,11 @@ namespace Bit.App.Pages
|
||||
if(Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
_absLayout.Children.Remove(_fab);
|
||||
ToolbarItems.Add(_closeItem);
|
||||
ToolbarItems.Add(_addItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
ToolbarItems.RemoveAt(0);
|
||||
_fab.Clicked = AddButton_Clicked;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,17 +15,7 @@
|
||||
</ContentPage.BindingContext>
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
|
||||
<ToolbarItem Text="{u:I18n Save}" Clicked="Save_Clicked" Order="Primary" />
|
||||
<ToolbarItem Text="{u:I18n Attachments}"
|
||||
Clicked="Attachments_Clicked"
|
||||
Order="Secondary"
|
||||
x:Name="_attachmentsItem" />
|
||||
<ToolbarItem Text="{u:I18n Delete}"
|
||||
Clicked="Delete_Clicked"
|
||||
Order="Secondary"
|
||||
IsDestructive="True"
|
||||
x:Name="_deleteItem" />
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ContentPage.Resources>
|
||||
@@ -33,16 +23,33 @@
|
||||
<u:InverseBoolConverter x:Key="inverseBool" />
|
||||
<u:StringHasValueConverter x:Key="stringHasValue" />
|
||||
<u:IsNotNullConverter x:Key="notNull" />
|
||||
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
|
||||
x:Key="closeItem" x:Name="_closeItem" />
|
||||
<ToolbarItem Text="{u:I18n Collections}"
|
||||
x:Key="collectionsItem"
|
||||
x:Name="_collectionsItem"
|
||||
Clicked="Collections_Clicked"
|
||||
Order="Secondary" />
|
||||
x:Key="collectionsItem"
|
||||
x:Name="_collectionsItem"
|
||||
Clicked="Collections_Clicked"
|
||||
Order="Secondary" />
|
||||
<ToolbarItem Text="{u:I18n Share}"
|
||||
x:Key="shareItem"
|
||||
x:Name="_shareItem"
|
||||
Clicked="Share_Clicked"
|
||||
Order="Secondary" />
|
||||
x:Key="shareItem"
|
||||
x:Name="_shareItem"
|
||||
Clicked="Share_Clicked"
|
||||
Order="Secondary" />
|
||||
<ToolbarItem Icon="more_vert.png" Clicked="More_Clicked" Order="Primary" x:Name="_moreItem"
|
||||
x:Key="moreItem"
|
||||
AutomationProperties.IsInAccessibleTree="True"
|
||||
AutomationProperties.Name="{u:I18n Options}" />
|
||||
<ToolbarItem Text="{u:I18n Attachments}"
|
||||
Clicked="Attachments_Clicked"
|
||||
Order="Secondary"
|
||||
x:Name="_attachmentsItem"
|
||||
x:Key="attachmentsItem" />
|
||||
<ToolbarItem Text="{u:I18n Delete}"
|
||||
Clicked="Delete_Clicked"
|
||||
Order="Secondary"
|
||||
IsDestructive="True"
|
||||
x:Name="_deleteItem"
|
||||
x:Key="deleteItem" />
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
|
||||
|
||||
@@ -46,14 +46,18 @@ namespace Bit.App.Pages
|
||||
_vm.DefaultUri = uri ?? appOptions?.Uri;
|
||||
_vm.Init();
|
||||
SetActivityIndicator();
|
||||
if(!_vm.EditMode || Device.RuntimePlatform == Device.iOS)
|
||||
if(_vm.EditMode && Device.RuntimePlatform == Device.Android)
|
||||
{
|
||||
ToolbarItems.Remove(_attachmentsItem);
|
||||
ToolbarItems.Remove(_deleteItem);
|
||||
ToolbarItems.Add(_attachmentsItem);
|
||||
ToolbarItems.Add(_deleteItem);
|
||||
}
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
if(Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
ToolbarItems.RemoveAt(0);
|
||||
ToolbarItems.Add(_closeItem);
|
||||
if(_vm.EditMode)
|
||||
{
|
||||
ToolbarItems.Add(_moreItem);
|
||||
}
|
||||
}
|
||||
|
||||
_typePicker.ItemDisplayBinding = new Binding("Key");
|
||||
@@ -237,6 +241,43 @@ namespace Bit.App.Pages
|
||||
}
|
||||
}
|
||||
|
||||
private async void More_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if(!DoOnce())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var options = new List<string> { AppResources.Attachments };
|
||||
if(_vm.EditMode)
|
||||
{
|
||||
options.Add(_vm.Cipher.OrganizationId != null ? AppResources.Share : AppResources.Collections);
|
||||
}
|
||||
var selection = await DisplayActionSheet(AppResources.Options, AppResources.Cancel,
|
||||
_vm.EditMode ? AppResources.Delete : null, options.ToArray());
|
||||
if(selection == AppResources.Delete)
|
||||
{
|
||||
if(await _vm.DeleteAsync())
|
||||
{
|
||||
await Navigation.PopModalAsync();
|
||||
}
|
||||
}
|
||||
else if(selection == AppResources.Attachments)
|
||||
{
|
||||
var page = new AttachmentsPage(_vm.CipherId);
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
else if(selection == AppResources.Collections)
|
||||
{
|
||||
var page = new CollectionsPage(_vm.CipherId);
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
else if(selection == AppResources.Share)
|
||||
{
|
||||
var page = new SharePage(_vm.CipherId);
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
}
|
||||
|
||||
private async void Close_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if(DoOnce())
|
||||
|
||||
@@ -367,6 +367,10 @@ namespace Bit.App.Pages
|
||||
|
||||
public async Task<bool> SubmitAsync()
|
||||
{
|
||||
if(Cipher == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.None)
|
||||
{
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.InternetConnectionRequiredMessage,
|
||||
@@ -381,10 +385,10 @@ namespace Bit.App.Pages
|
||||
return false;
|
||||
}
|
||||
|
||||
Cipher.Fields = Fields.Any() ? Fields.Select(f => f.Field).ToList() : null;
|
||||
Cipher.Fields = Fields != null && Fields.Any() ? Fields.Select(f => f.Field).ToList() : null;
|
||||
if(Cipher.Login != null)
|
||||
{
|
||||
Cipher.Login.Uris = Uris.ToList();
|
||||
Cipher.Login.Uris = Uris?.ToList();
|
||||
if(!EditMode && Cipher.Type == CipherType.Login && (Cipher.Login.Uris?.Count ?? 0) == 1 &&
|
||||
string.IsNullOrWhiteSpace(Cipher.Login.Uris.First().Uri))
|
||||
{
|
||||
@@ -406,6 +410,10 @@ namespace Bit.App.Pages
|
||||
}
|
||||
|
||||
var cipher = await _cipherService.EncryptAsync(Cipher);
|
||||
if(cipher == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
await _deviceActionService.ShowLoadingAsync(AppResources.Saving);
|
||||
|
||||
@@ -3,6 +3,8 @@ using Bit.App.Resources;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Utilities;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
@@ -31,7 +33,15 @@ namespace Bit.App.Pages
|
||||
base.OnAppearing();
|
||||
await LoadOnAppearedAsync(_mainLayout, false, async () =>
|
||||
{
|
||||
await _vm.LoadAsync();
|
||||
try
|
||||
{
|
||||
await _vm.LoadAsync();
|
||||
}
|
||||
catch(Exception e) when(e.Message.Contains("No key."))
|
||||
{
|
||||
await Task.Delay(5000);
|
||||
await _vm.LoadAsync();
|
||||
}
|
||||
}, _mainContent);
|
||||
}
|
||||
|
||||
|
||||
@@ -112,6 +112,10 @@ namespace Bit.App.Pages
|
||||
|
||||
public async Task SelectCipherAsync(CipherView cipher, bool fuzzy)
|
||||
{
|
||||
if(cipher == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(_deviceActionService.SystemMajorVersion() < 21)
|
||||
{
|
||||
await AppHelpers.CipherListOptions(Page, cipher);
|
||||
|
||||
@@ -15,13 +15,11 @@
|
||||
<pages:CiphersPageViewModel />
|
||||
</ContentPage.BindingContext>
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<u:DateTimeConverter x:Key="dateTime" />
|
||||
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
|
||||
x:Name="_closeItem" x:Key="closeItem" />
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
|
||||
@@ -31,12 +29,14 @@
|
||||
VerticalOptions="FillAndExpand"
|
||||
HorizontalOptions="FillAndExpand"
|
||||
Spacing="0"
|
||||
Padding="0">
|
||||
Padding="0"
|
||||
x:Name="_titleLayout">
|
||||
<controls:MiButton
|
||||
StyleClass="btn-title, btn-title-platform"
|
||||
Text=""
|
||||
VerticalOptions="CenterAndExpand"
|
||||
Clicked="BackButton_Clicked" />
|
||||
Clicked="BackButton_Clicked"
|
||||
x:Name="_backButton" />
|
||||
<SearchBar
|
||||
x:Name="_searchBar"
|
||||
HorizontalOptions="FillAndExpand"
|
||||
|
||||
@@ -40,9 +40,10 @@ namespace Bit.App.Pages
|
||||
_vm.PageTitle = AppResources.SearchVault;
|
||||
}
|
||||
|
||||
if(Device.RuntimePlatform == Device.Android)
|
||||
if(Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
ToolbarItems.RemoveAt(0);
|
||||
ToolbarItems.Add(_closeItem);
|
||||
_titleLayout.Children.Remove(_backButton);
|
||||
}
|
||||
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||
}
|
||||
@@ -121,12 +122,9 @@ namespace Bit.App.Pages
|
||||
}
|
||||
}
|
||||
|
||||
private async void Close_Clicked(object sender, System.EventArgs e)
|
||||
private void Close_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if(DoOnce())
|
||||
{
|
||||
await Navigation.PopModalAsync();
|
||||
}
|
||||
GoBack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
</ContentPage.BindingContext>
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Icon="search.png" Clicked="Search_Clicked" />
|
||||
<ToolbarItem Icon="search.png" Clicked="Search_Clicked"
|
||||
AutomationProperties.IsInAccessibleTree="True"
|
||||
AutomationProperties.Name="{u:I18n Search}" />
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ContentPage.Resources>
|
||||
@@ -29,6 +31,10 @@
|
||||
Clicked="Lock_Clicked" Order="Secondary" />
|
||||
<ToolbarItem x:Name="_exitItem" x:Key="exitItem" Text="{u:I18n Exit}"
|
||||
Clicked="Exit_Clicked" Order="Secondary" />
|
||||
<ToolbarItem x:Name="_addItem" x:Key="addItem" Icon="plus.png"
|
||||
Clicked="AddButton_Clicked" Order="Primary"
|
||||
AutomationProperties.IsInAccessibleTree="True"
|
||||
AutomationProperties.Name="{u:I18n AddItem}" />
|
||||
|
||||
<DataTemplate x:Key="cipherTemplate"
|
||||
x:DataType="pages:GroupingsPageListItem">
|
||||
@@ -137,7 +143,9 @@
|
||||
x:Name="_fab"
|
||||
ImageName="plus.png"
|
||||
AbsoluteLayout.LayoutFlags="PositionProportional"
|
||||
AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize">
|
||||
AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize"
|
||||
AutomationProperties.IsInAccessibleTree="True"
|
||||
AutomationProperties.Name="{u:I18n AddItem}">
|
||||
</fab:FloatingActionButtonView>
|
||||
</AbsoluteLayout>
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Utilities;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
@@ -50,6 +49,7 @@ namespace Bit.App.Pages
|
||||
if(Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
_absLayout.Children.Remove(_fab);
|
||||
ToolbarItems.Add(_addItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -78,6 +78,10 @@ namespace Bit.App.Pages
|
||||
}
|
||||
else if(message.Command == "syncCompleted")
|
||||
{
|
||||
if(!_vm.LoadedOnce)
|
||||
{
|
||||
return;
|
||||
}
|
||||
await Task.Delay(500);
|
||||
Device.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
@@ -92,8 +96,15 @@ namespace Bit.App.Pages
|
||||
{
|
||||
if(!_syncService.SyncInProgress)
|
||||
{
|
||||
await Task.Delay(500);
|
||||
await _vm.LoadAsync();
|
||||
try
|
||||
{
|
||||
await _vm.LoadAsync();
|
||||
}
|
||||
catch(Exception e) when(e.Message.Contains("No key."))
|
||||
{
|
||||
await Task.Delay(5000);
|
||||
await _vm.LoadAsync();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -105,7 +116,7 @@ namespace Bit.App.Pages
|
||||
}
|
||||
// Forced sync if for some reason we have no data after a v1 migration
|
||||
if(_vm.MainPage && !_syncService.SyncInProgress && migratedFromV1.GetValueOrDefault() &&
|
||||
!_vm.HasCiphers && !_vm.HasFolders &&
|
||||
!_vm.HasCiphers &&
|
||||
Xamarin.Essentials.Connectivity.NetworkAccess != Xamarin.Essentials.NetworkAccess.None)
|
||||
{
|
||||
var triedV1ReSync = await _storageService.GetAsync<bool?>(Constants.TriedV1Resync);
|
||||
|
||||
@@ -126,6 +126,7 @@ namespace Bit.App.Pages
|
||||
public ExtendedObservableCollection<GroupingsPageListGroup> GroupedItems { get; set; }
|
||||
public Command RefreshCommand { get; set; }
|
||||
public Command<CipherView> CipherOptionsCommand { get; set; }
|
||||
public bool LoadedOnce { get; set; }
|
||||
|
||||
public async Task LoadAsync()
|
||||
{
|
||||
@@ -134,6 +135,7 @@ namespace Bit.App.Pages
|
||||
return;
|
||||
}
|
||||
_doingLoad = true;
|
||||
LoadedOnce = true;
|
||||
ShowNoData = false;
|
||||
Loading = true;
|
||||
ShowList = false;
|
||||
|
||||
@@ -16,13 +16,6 @@
|
||||
<pages:ViewPageViewModel />
|
||||
</ContentPage.BindingContext>
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1" />
|
||||
<ToolbarItem Text="{u:I18n Edit}" Clicked="EditToolbarItem_Clicked" Order="Primary" />
|
||||
<ToolbarItem Text="{u:I18n Attachments}" Clicked="Attachments_Clicked" Order="Secondary" />
|
||||
<ToolbarItem Text="{u:I18n Delete}" Clicked="Delete_Clicked" Order="Secondary" IsDestructive="True" />
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<u:InverseBoolConverter x:Key="inverseBool" />
|
||||
@@ -38,6 +31,18 @@
|
||||
x:Name="_shareItem"
|
||||
Clicked="Share_Clicked"
|
||||
Order="Secondary" />
|
||||
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
|
||||
x:Name="_closeItem" x:Key="closeItem" />
|
||||
<ToolbarItem Text="{u:I18n Edit}" Clicked="EditToolbarItem_Clicked" Order="Primary"
|
||||
x:Name="_editItem" x:Key="editItem" />
|
||||
<ToolbarItem Icon="more_vert.png" Clicked="More_Clicked" Order="Primary"
|
||||
x:Name="_moreItem" x:Key="moreItem"
|
||||
AutomationProperties.IsInAccessibleTree="True"
|
||||
AutomationProperties.Name="{u:I18n Options}" />
|
||||
<ToolbarItem Text="{u:I18n Attachments}" Clicked="Attachments_Clicked" Order="Secondary"
|
||||
x:Name="_attachmentsItem" x:Key="attachmentsItem" />
|
||||
<ToolbarItem Text="{u:I18n Delete}" Clicked="Delete_Clicked" Order="Secondary" IsDestructive="True"
|
||||
x:Name="_deleteItem" x:Key="deleteItem" />
|
||||
|
||||
<ScrollView x:Key="scrollView" x:Name="_scrollView">
|
||||
<StackLayout Spacing="20" x:Name="_mainLayout">
|
||||
@@ -632,7 +637,9 @@
|
||||
x:Name="_fab"
|
||||
ImageName="pencil.png"
|
||||
AbsoluteLayout.LayoutFlags="PositionProportional"
|
||||
AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize">
|
||||
AbsoluteLayout.LayoutBounds="1, 1, AutoSize, AutoSize"
|
||||
AutomationProperties.IsInAccessibleTree="True"
|
||||
AutomationProperties.Name="{u:I18n EditItem}">
|
||||
</fab:FloatingActionButtonView>
|
||||
</AbsoluteLayout>
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.App.Resources;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
@@ -25,15 +26,16 @@ namespace Bit.App.Pages
|
||||
if(Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
_absLayout.Children.Remove(_fab);
|
||||
ToolbarItems.RemoveAt(2);
|
||||
ToolbarItems.RemoveAt(2);
|
||||
ToolbarItems.Add(_closeItem);
|
||||
ToolbarItems.Add(_editItem);
|
||||
ToolbarItems.Add(_moreItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
ToolbarItems.RemoveAt(0);
|
||||
ToolbarItems.RemoveAt(0);
|
||||
_fab.Clicked = EditButton_Clicked;
|
||||
_mainLayout.Padding = new Thickness(0, 0, 0, 75);
|
||||
ToolbarItems.Add(_attachmentsItem);
|
||||
ToolbarItems.Add(_deleteItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,6 +147,40 @@ namespace Bit.App.Pages
|
||||
}
|
||||
}
|
||||
|
||||
private async void More_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if(!DoOnce())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var options = new List<string> { AppResources.Attachments };
|
||||
options.Add(_vm.Cipher.OrganizationId != null ? AppResources.Share : AppResources.Collections);
|
||||
var selection = await DisplayActionSheet(AppResources.Options, AppResources.Cancel,
|
||||
AppResources.Delete, options.ToArray());
|
||||
if(selection == AppResources.Delete)
|
||||
{
|
||||
if(await _vm.DeleteAsync())
|
||||
{
|
||||
await Navigation.PopModalAsync();
|
||||
}
|
||||
}
|
||||
else if(selection == AppResources.Attachments)
|
||||
{
|
||||
var page = new AttachmentsPage(_vm.CipherId);
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
else if(selection == AppResources.Collections)
|
||||
{
|
||||
var page = new CollectionsPage(_vm.CipherId);
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
else if(selection == AppResources.Share)
|
||||
{
|
||||
var page = new SharePage(_vm.CipherId);
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
}
|
||||
|
||||
private async void Close_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if(DoOnce())
|
||||
|
||||
@@ -94,7 +94,11 @@ namespace Bit.App.Services
|
||||
if((uri.StartsWith("http://") || uri.StartsWith("https://")) &&
|
||||
Uri.TryCreate(uri, UriKind.Absolute, out var parsedUri))
|
||||
{
|
||||
Browser.OpenAsync(uri, BrowserLaunchMode.External);
|
||||
try
|
||||
{
|
||||
Browser.OpenAsync(uri, BrowserLaunchMode.External);
|
||||
}
|
||||
catch(FeatureNotSupportedException) { }
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Bit.Core.Services
|
||||
{
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver()
|
||||
};
|
||||
private readonly HttpClient _httpClient = new HttpClient();
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly ITokenService _tokenService;
|
||||
private readonly IPlatformUtilsService _platformUtilsService;
|
||||
private readonly Func<bool, Task> _logoutCallbackAsync;
|
||||
@@ -31,13 +31,22 @@ namespace Bit.Core.Services
|
||||
public ApiService(
|
||||
ITokenService tokenService,
|
||||
IPlatformUtilsService platformUtilsService,
|
||||
Func<bool, Task> logoutCallbackAsync)
|
||||
Func<bool, Task> logoutCallbackAsync,
|
||||
HttpMessageHandler httpMessageHandler = null)
|
||||
{
|
||||
_tokenService = tokenService;
|
||||
_platformUtilsService = platformUtilsService;
|
||||
_logoutCallbackAsync = logoutCallbackAsync;
|
||||
var device = _platformUtilsService.GetDevice();
|
||||
_deviceType = device.ToString();
|
||||
if(httpMessageHandler != null)
|
||||
{
|
||||
_httpClient = new HttpClient(httpMessageHandler);
|
||||
}
|
||||
else
|
||||
{
|
||||
_httpClient = new HttpClient();
|
||||
}
|
||||
}
|
||||
|
||||
public bool UrlsSet { get; private set; }
|
||||
|
||||
@@ -310,7 +310,7 @@ namespace Bit.Core.Services
|
||||
{
|
||||
options.MinNumber = 9;
|
||||
}
|
||||
|
||||
|
||||
if(options.MinSpecial == null)
|
||||
{
|
||||
options.MinSpecial = 0;
|
||||
@@ -354,7 +354,15 @@ namespace Bit.Core.Services
|
||||
}
|
||||
var tasks = history.Select(async item =>
|
||||
{
|
||||
if(item == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var encrypted = await _cryptoService.EncryptAsync(item.Password);
|
||||
if(encrypted == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new GeneratedPasswordHistory
|
||||
{
|
||||
Password = encrypted.EncryptedString,
|
||||
@@ -362,7 +370,7 @@ namespace Bit.Core.Services
|
||||
};
|
||||
});
|
||||
var h = await Task.WhenAll(tasks);
|
||||
return h.ToList();
|
||||
return h.Where(x => x != null).ToList();
|
||||
}
|
||||
|
||||
private async Task<List<GeneratedPasswordHistory>> DecryptHistoryAsync(List<GeneratedPasswordHistory> history)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Bit.Core.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Bit.Core.Utilities
|
||||
@@ -11,7 +12,7 @@ namespace Bit.Core.Utilities
|
||||
public static Dictionary<string, object> RegisteredServices { get; set; } = new Dictionary<string, object>();
|
||||
public static bool Inited { get; set; }
|
||||
|
||||
public static void Init()
|
||||
public static void Init(HttpClientHandler httpClientHandler = null)
|
||||
{
|
||||
if(Inited)
|
||||
{
|
||||
@@ -31,7 +32,8 @@ namespace Bit.Core.Utilities
|
||||
var cryptoFunctionService = new PclCryptoFunctionService(cryptoPrimitiveService);
|
||||
var cryptoService = new CryptoService(storageService, secureStorageService, cryptoFunctionService);
|
||||
var tokenService = new TokenService(storageService);
|
||||
var apiService = new ApiService(tokenService, platformUtilsService, (bool expired) => Task.FromResult(0));
|
||||
var apiService = new ApiService(tokenService, platformUtilsService, (bool expired) => Task.FromResult(0),
|
||||
httpClientHandler);
|
||||
var appIdService = new AppIdService(storageService);
|
||||
var userService = new UserService(storageService, tokenService);
|
||||
var settingsService = new SettingsService(userService, storageService);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.8bit.bitwarden</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.0.1</string>
|
||||
<string>2.0.6</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>50</string>
|
||||
<key>CFBundleIconName</key>
|
||||
|
||||
@@ -40,14 +40,17 @@ namespace Bit.iOS.Renderers
|
||||
}
|
||||
if(e.NewElement != null)
|
||||
{
|
||||
Control.LoadRequest(new NSUrlRequest(new NSUrl(Element.Uri)));
|
||||
if(Element.Uri != null)
|
||||
{
|
||||
Control.LoadRequest(new NSUrlRequest(new NSUrl(Element.Uri)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
if(e.PropertyName == HybridWebView.UriProperty.PropertyName)
|
||||
if(e.PropertyName == HybridWebView.UriProperty.PropertyName && Element.Uri != null)
|
||||
{
|
||||
Control.LoadRequest(new NSUrlRequest(new NSUrl(Element.Uri)));
|
||||
}
|
||||
|
||||
BIN
src/iOS/Resources/more.png
Normal file
|
After Width: | Height: | Size: 145 B |
BIN
src/iOS/Resources/more@2x.png
Normal file
|
After Width: | Height: | Size: 348 B |
BIN
src/iOS/Resources/more@3x.png
Normal file
|
After Width: | Height: | Size: 555 B |
BIN
src/iOS/Resources/more_vert.png
Normal file
|
After Width: | Height: | Size: 164 B |
BIN
src/iOS/Resources/more_vert@2x.png
Normal file
|
After Width: | Height: | Size: 242 B |
BIN
src/iOS/Resources/more_vert@3x.png
Normal file
|
After Width: | Height: | Size: 338 B |
@@ -132,6 +132,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="Xamarin.iOS" />
|
||||
@@ -331,4 +332,22 @@
|
||||
<Visible>false</Visible>
|
||||
</ImageAsset>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="Resources\more%403x.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="Resources\more.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="Resources\more%402x.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="Resources\more_vert%403x.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="Resources\more_vert.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="Resources\more_vert%402x.png" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 4.8 KiB |