mirror of
https://github.com/bitwarden/mobile.git
synced 2024-11-22 11:35:21 +01:00
Support for Disable Send policy (#1271)
* add support for disable send policy * cleanup * show/hide options support for send search results * additional failsafes and copy function consolidation * added missing disabled send icon to android renderer * async fix and string updates
This commit is contained in:
parent
20d5c6a63a
commit
3799eb4603
@ -102,6 +102,7 @@ namespace Bit.Droid.Renderers
|
|||||||
Icon = view.FindViewById<TextView>(Resource.Id.SendCellIcon);
|
Icon = view.FindViewById<TextView>(Resource.Id.SendCellIcon);
|
||||||
Name = view.FindViewById<TextView>(Resource.Id.SendCellName);
|
Name = view.FindViewById<TextView>(Resource.Id.SendCellName);
|
||||||
SubTitle = view.FindViewById<TextView>(Resource.Id.SendCellSubTitle);
|
SubTitle = view.FindViewById<TextView>(Resource.Id.SendCellSubTitle);
|
||||||
|
DisabledIcon = view.FindViewById<TextView>(Resource.Id.SendCellDisabledIcon);
|
||||||
HasPasswordIcon = view.FindViewById<TextView>(Resource.Id.SendCellHasPasswordIcon);
|
HasPasswordIcon = view.FindViewById<TextView>(Resource.Id.SendCellHasPasswordIcon);
|
||||||
MaxAccessCountReachedIcon = view.FindViewById<TextView>(Resource.Id.SendCellMaxAccessCountReachedIcon);
|
MaxAccessCountReachedIcon = view.FindViewById<TextView>(Resource.Id.SendCellMaxAccessCountReachedIcon);
|
||||||
ExpiredIcon = view.FindViewById<TextView>(Resource.Id.SendCellExpiredIcon);
|
ExpiredIcon = view.FindViewById<TextView>(Resource.Id.SendCellExpiredIcon);
|
||||||
@ -110,6 +111,7 @@ namespace Bit.Droid.Renderers
|
|||||||
MoreButton.Click += MoreButton_Click;
|
MoreButton.Click += MoreButton_Click;
|
||||||
|
|
||||||
Icon.Typeface = _faTypeface;
|
Icon.Typeface = _faTypeface;
|
||||||
|
DisabledIcon.Typeface = _faTypeface;
|
||||||
HasPasswordIcon.Typeface = _faTypeface;
|
HasPasswordIcon.Typeface = _faTypeface;
|
||||||
MaxAccessCountReachedIcon.Typeface = _faTypeface;
|
MaxAccessCountReachedIcon.Typeface = _faTypeface;
|
||||||
ExpiredIcon.Typeface = _faTypeface;
|
ExpiredIcon.Typeface = _faTypeface;
|
||||||
@ -120,12 +122,18 @@ namespace Bit.Droid.Renderers
|
|||||||
Icon.SetTextSize(ComplexUnitType.Pt, 10);
|
Icon.SetTextSize(ComplexUnitType.Pt, 10);
|
||||||
Name.SetTextSize(ComplexUnitType.Sp, (float)Device.GetNamedSize(NamedSize.Medium, typeof(Label)));
|
Name.SetTextSize(ComplexUnitType.Sp, (float)Device.GetNamedSize(NamedSize.Medium, typeof(Label)));
|
||||||
SubTitle.SetTextSize(ComplexUnitType.Sp, small);
|
SubTitle.SetTextSize(ComplexUnitType.Sp, small);
|
||||||
|
DisabledIcon.SetTextSize(ComplexUnitType.Sp, small);
|
||||||
HasPasswordIcon.SetTextSize(ComplexUnitType.Sp, small);
|
HasPasswordIcon.SetTextSize(ComplexUnitType.Sp, small);
|
||||||
MaxAccessCountReachedIcon.SetTextSize(ComplexUnitType.Sp, small);
|
MaxAccessCountReachedIcon.SetTextSize(ComplexUnitType.Sp, small);
|
||||||
ExpiredIcon.SetTextSize(ComplexUnitType.Sp, small);
|
ExpiredIcon.SetTextSize(ComplexUnitType.Sp, small);
|
||||||
PendingDeleteIcon.SetTextSize(ComplexUnitType.Sp, small);
|
PendingDeleteIcon.SetTextSize(ComplexUnitType.Sp, small);
|
||||||
MoreButton.SetTextSize(ComplexUnitType.Sp, 25);
|
MoreButton.SetTextSize(ComplexUnitType.Sp, 25);
|
||||||
|
|
||||||
|
if (!SendViewCell.ShowOptions)
|
||||||
|
{
|
||||||
|
MoreButton.Visibility = ViewStates.Gone;
|
||||||
|
}
|
||||||
|
|
||||||
AddView(view);
|
AddView(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,6 +143,7 @@ namespace Bit.Droid.Renderers
|
|||||||
public TextView Icon { get; set; }
|
public TextView Icon { get; set; }
|
||||||
public TextView Name { get; set; }
|
public TextView Name { get; set; }
|
||||||
public TextView SubTitle { get; set; }
|
public TextView SubTitle { get; set; }
|
||||||
|
public TextView DisabledIcon { get; set; }
|
||||||
public TextView HasPasswordIcon { get; set; }
|
public TextView HasPasswordIcon { get; set; }
|
||||||
public TextView MaxAccessCountReachedIcon { get; set; }
|
public TextView MaxAccessCountReachedIcon { get; set; }
|
||||||
public TextView ExpiredIcon { get; set; }
|
public TextView ExpiredIcon { get; set; }
|
||||||
@ -148,6 +157,7 @@ namespace Bit.Droid.Renderers
|
|||||||
var send = sendCell.Send;
|
var send = sendCell.Send;
|
||||||
Name.Text = send.Name;
|
Name.Text = send.Name;
|
||||||
SubTitle.Text = send.DisplayDate;
|
SubTitle.Text = send.DisplayDate;
|
||||||
|
DisabledIcon.Visibility = send.Disabled ? ViewStates.Visible : ViewStates.Gone;
|
||||||
HasPasswordIcon.Visibility = send.HasPassword ? ViewStates.Visible : ViewStates.Gone;
|
HasPasswordIcon.Visibility = send.HasPassword ? ViewStates.Visible : ViewStates.Gone;
|
||||||
MaxAccessCountReachedIcon.Visibility = send.MaxAccessCountReached ? ViewStates.Visible : ViewStates.Gone;
|
MaxAccessCountReachedIcon.Visibility = send.MaxAccessCountReached ? ViewStates.Visible : ViewStates.Gone;
|
||||||
ExpiredIcon.Visibility = send.Expired ? ViewStates.Visible : ViewStates.Gone;
|
ExpiredIcon.Visibility = send.Expired ? ViewStates.Visible : ViewStates.Gone;
|
||||||
@ -172,6 +182,7 @@ namespace Bit.Droid.Renderers
|
|||||||
Name.SetTextColor(textColor);
|
Name.SetTextColor(textColor);
|
||||||
SubTitle.SetTextColor(mutedColor);
|
SubTitle.SetTextColor(mutedColor);
|
||||||
Icon.SetTextColor(mutedColor);
|
Icon.SetTextColor(mutedColor);
|
||||||
|
DisabledIcon.SetTextColor(mutedColor);
|
||||||
HasPasswordIcon.SetTextColor(mutedColor);
|
HasPasswordIcon.SetTextColor(mutedColor);
|
||||||
MaxAccessCountReachedIcon.SetTextColor(mutedColor);
|
MaxAccessCountReachedIcon.SetTextColor(mutedColor);
|
||||||
ExpiredIcon.SetTextColor(mutedColor);
|
ExpiredIcon.SetTextColor(mutedColor);
|
||||||
|
@ -43,6 +43,14 @@
|
|||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:text="Name" />
|
android:text="Name" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/SendCellDisabledIcon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="" />
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/SendCellHasPasswordIcon"
|
android:id="@+id/SendCellHasPasswordIcon"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -124,6 +124,7 @@
|
|||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
Text=""
|
Text=""
|
||||||
|
IsVisible="{Binding ShowOptions, Mode=OneWay}"
|
||||||
StyleClass="list-row-button, list-row-button-platform, btn-disabled"
|
StyleClass="list-row-button, list-row-button-platform, btn-disabled"
|
||||||
Clicked="MoreButton_Clicked"
|
Clicked="MoreButton_Clicked"
|
||||||
VerticalOptions="CenterAndExpand"
|
VerticalOptions="CenterAndExpand"
|
||||||
|
@ -15,6 +15,9 @@ namespace Bit.App.Controls
|
|||||||
|
|
||||||
public static readonly BindableProperty ButtonCommandProperty = BindableProperty.Create(
|
public static readonly BindableProperty ButtonCommandProperty = BindableProperty.Create(
|
||||||
nameof(ButtonCommand), typeof(Command<SendView>), typeof(SendViewCell));
|
nameof(ButtonCommand), typeof(Command<SendView>), typeof(SendViewCell));
|
||||||
|
|
||||||
|
public static readonly BindableProperty ShowOptionsProperty = BindableProperty.Create(
|
||||||
|
nameof(ShowOptions), typeof(bool), typeof(SendViewCell));
|
||||||
|
|
||||||
private readonly IEnvironmentService _environmentService;
|
private readonly IEnvironmentService _environmentService;
|
||||||
|
|
||||||
@ -47,6 +50,12 @@ namespace Bit.App.Controls
|
|||||||
set => SetValue(ButtonCommandProperty, value);
|
set => SetValue(ButtonCommandProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ShowOptions
|
||||||
|
{
|
||||||
|
get => GetValue(ShowOptionsProperty) is bool && (bool)GetValue(ShowOptionsProperty);
|
||||||
|
set => SetValue(ShowOptionsProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnPropertyChanged(string propertyName = null)
|
protected override void OnPropertyChanged(string propertyName = null)
|
||||||
{
|
{
|
||||||
base.OnPropertyChanged(propertyName);
|
base.OnPropertyChanged(propertyName);
|
||||||
@ -58,6 +67,10 @@ namespace Bit.App.Controls
|
|||||||
{
|
{
|
||||||
_viewModel.Send = Send;
|
_viewModel.Send = Send;
|
||||||
}
|
}
|
||||||
|
else if (propertyName == ShowOptionsProperty.PropertyName)
|
||||||
|
{
|
||||||
|
_viewModel.ShowOptions = ShowOptions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnBindingContextChanged()
|
protected override void OnBindingContextChanged()
|
||||||
|
@ -6,11 +6,18 @@ namespace Bit.App.Controls
|
|||||||
public class SendViewCellViewModel : ExtendedViewModel
|
public class SendViewCellViewModel : ExtendedViewModel
|
||||||
{
|
{
|
||||||
private SendView _send;
|
private SendView _send;
|
||||||
|
private bool _showOptions;
|
||||||
|
|
||||||
public SendView Send
|
public SendView Send
|
||||||
{
|
{
|
||||||
get => _send;
|
get => _send;
|
||||||
set => SetProperty(ref _send, value);
|
set => SetProperty(ref _send, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ShowOptions
|
||||||
|
{
|
||||||
|
get => _showOptions;
|
||||||
|
set => SetProperty(ref _showOptions, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
</ContentPage.BindingContext>
|
</ContentPage.BindingContext>
|
||||||
|
|
||||||
<ContentPage.ToolbarItems>
|
<ContentPage.ToolbarItems>
|
||||||
<ToolbarItem Text="{u:I18n Save}" Clicked="Save_Clicked" Order="Primary" />
|
<ToolbarItem Text="{u:I18n Save}" Clicked="Save_Clicked" Order="Primary"
|
||||||
|
x:Key="saveItem" x:Name="_saveItem"/>
|
||||||
</ContentPage.ToolbarItems>
|
</ContentPage.ToolbarItems>
|
||||||
|
|
||||||
<ContentPage.Resources>
|
<ContentPage.Resources>
|
||||||
@ -76,6 +77,18 @@
|
|||||||
<ScrollView x:Key="scrollView" x:Name="_scrollView">
|
<ScrollView x:Key="scrollView" x:Name="_scrollView">
|
||||||
<StackLayout Spacing="20">
|
<StackLayout Spacing="20">
|
||||||
<StackLayout StyleClass="box">
|
<StackLayout StyleClass="box">
|
||||||
|
<Frame
|
||||||
|
IsVisible="{Binding SendEnabled, Converter={StaticResource inverseBool}}"
|
||||||
|
Padding="10"
|
||||||
|
Margin="0, 12, 0, 0"
|
||||||
|
HasShadow="False"
|
||||||
|
BackgroundColor="Transparent"
|
||||||
|
BorderColor="Accent">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n SendDisabledWarning}"
|
||||||
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
|
HorizontalTextAlignment="Center" />
|
||||||
|
</Frame>
|
||||||
<StackLayout StyleClass="box-row">
|
<StackLayout StyleClass="box-row">
|
||||||
<Label
|
<Label
|
||||||
Text="{u:I18n Name}"
|
Text="{u:I18n Name}"
|
||||||
@ -83,6 +96,7 @@
|
|||||||
<Entry
|
<Entry
|
||||||
x:Name="_nameEntry"
|
x:Name="_nameEntry"
|
||||||
Text="{Binding Send.Name}"
|
Text="{Binding Send.Name}"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
StyleClass="box-value" />
|
StyleClass="box-value" />
|
||||||
<Label
|
<Label
|
||||||
Text="{u:I18n NameInfo}"
|
Text="{u:I18n NameInfo}"
|
||||||
@ -186,6 +200,7 @@
|
|||||||
HorizontalTextAlignment="Center" />
|
HorizontalTextAlignment="Center" />
|
||||||
<Button
|
<Button
|
||||||
Text="{u:I18n ChooseFile}"
|
Text="{u:I18n ChooseFile}"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
StyleClass="box-button-row"
|
StyleClass="box-button-row"
|
||||||
Clicked="ChooseFile_Clicked" />
|
Clicked="ChooseFile_Clicked" />
|
||||||
<Label
|
<Label
|
||||||
@ -210,6 +225,7 @@
|
|||||||
x:Name="_textEditor"
|
x:Name="_textEditor"
|
||||||
AutoSize="TextChanges"
|
AutoSize="TextChanges"
|
||||||
Text="{Binding Send.Text.Text}"
|
Text="{Binding Send.Text.Text}"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
StyleClass="box-value"
|
StyleClass="box-value"
|
||||||
Margin="{Binding EditorMargins}" />
|
Margin="{Binding EditorMargins}" />
|
||||||
<BoxView
|
<BoxView
|
||||||
@ -229,6 +245,7 @@
|
|||||||
HorizontalOptions="StartAndExpand" />
|
HorizontalOptions="StartAndExpand" />
|
||||||
<Switch
|
<Switch
|
||||||
IsToggled="{Binding Send.Text.Hidden}"
|
IsToggled="{Binding Send.Text.Hidden}"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
HorizontalOptions="End"
|
HorizontalOptions="End"
|
||||||
Margin="10,0,0,0" />
|
Margin="10,0,0,0" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
@ -241,6 +258,7 @@
|
|||||||
HorizontalOptions="StartAndExpand" />
|
HorizontalOptions="StartAndExpand" />
|
||||||
<Switch
|
<Switch
|
||||||
IsToggled="{Binding ShareOnSave}"
|
IsToggled="{Binding ShareOnSave}"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
HorizontalOptions="End"
|
HorizontalOptions="End"
|
||||||
Margin="10,0,0,0" />
|
Margin="10,0,0,0" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
@ -281,6 +299,7 @@
|
|||||||
IsVisible="{Binding EditMode, Converter={StaticResource inverseBool}}"
|
IsVisible="{Binding EditMode, Converter={StaticResource inverseBool}}"
|
||||||
ItemsSource="{Binding DeletionTypeOptions, Mode=OneTime}"
|
ItemsSource="{Binding DeletionTypeOptions, Mode=OneTime}"
|
||||||
SelectedIndex="{Binding DeletionDateTypeSelectedIndex}"
|
SelectedIndex="{Binding DeletionDateTypeSelectedIndex}"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
StyleClass="box-value"
|
StyleClass="box-value"
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
AutomationProperties.Name="{u:I18n DeletionTime}" />
|
AutomationProperties.Name="{u:I18n DeletionTime}" />
|
||||||
@ -294,12 +313,14 @@
|
|||||||
<controls:ExtendedDatePicker
|
<controls:ExtendedDatePicker
|
||||||
NullableDate="{Binding DeletionDate, Mode=TwoWay}"
|
NullableDate="{Binding DeletionDate, Mode=TwoWay}"
|
||||||
Format="d"
|
Format="d"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
AutomationProperties.Name="{u:I18n DeletionDate}"
|
AutomationProperties.Name="{u:I18n DeletionDate}"
|
||||||
Grid.Column="0" />
|
Grid.Column="0" />
|
||||||
<controls:ExtendedTimePicker
|
<controls:ExtendedTimePicker
|
||||||
NullableTime="{Binding DeletionTime, Mode=TwoWay}"
|
NullableTime="{Binding DeletionTime, Mode=TwoWay}"
|
||||||
Format="t"
|
Format="t"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
AutomationProperties.Name="{u:I18n DeletionTime}"
|
AutomationProperties.Name="{u:I18n DeletionTime}"
|
||||||
Grid.Column="1" />
|
Grid.Column="1" />
|
||||||
@ -318,6 +339,7 @@
|
|||||||
IsVisible="{Binding EditMode, Converter={StaticResource inverseBool}}"
|
IsVisible="{Binding EditMode, Converter={StaticResource inverseBool}}"
|
||||||
ItemsSource="{Binding ExpirationTypeOptions, Mode=OneTime}"
|
ItemsSource="{Binding ExpirationTypeOptions, Mode=OneTime}"
|
||||||
SelectedIndex="{Binding ExpirationDateTypeSelectedIndex}"
|
SelectedIndex="{Binding ExpirationDateTypeSelectedIndex}"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
StyleClass="box-value"
|
StyleClass="box-value"
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
AutomationProperties.Name="{u:I18n ExpirationTime}" />
|
AutomationProperties.Name="{u:I18n ExpirationTime}" />
|
||||||
@ -332,6 +354,7 @@
|
|||||||
NullableDate="{Binding ExpirationDate, Mode=TwoWay}"
|
NullableDate="{Binding ExpirationDate, Mode=TwoWay}"
|
||||||
PlaceHolder="mm/dd/yyyy"
|
PlaceHolder="mm/dd/yyyy"
|
||||||
Format="d"
|
Format="d"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
AutomationProperties.Name="{u:I18n ExpirationDate}"
|
AutomationProperties.Name="{u:I18n ExpirationDate}"
|
||||||
Grid.Column="0" />
|
Grid.Column="0" />
|
||||||
@ -339,6 +362,7 @@
|
|||||||
NullableTime="{Binding ExpirationTime, Mode=TwoWay}"
|
NullableTime="{Binding ExpirationTime, Mode=TwoWay}"
|
||||||
PlaceHolder="--:-- --"
|
PlaceHolder="--:-- --"
|
||||||
Format="t"
|
Format="t"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
AutomationProperties.IsInAccessibleTree="True"
|
AutomationProperties.IsInAccessibleTree="True"
|
||||||
AutomationProperties.Name="{u:I18n ExpirationTime}"
|
AutomationProperties.Name="{u:I18n ExpirationTime}"
|
||||||
Grid.Column="1" />
|
Grid.Column="1" />
|
||||||
@ -356,6 +380,7 @@
|
|||||||
WidthRequest="110"
|
WidthRequest="110"
|
||||||
HeightRequest="{Binding SegmentedButtonHeight}"
|
HeightRequest="{Binding SegmentedButtonHeight}"
|
||||||
FontSize="{Binding SegmentedButtonFontSize}"
|
FontSize="{Binding SegmentedButtonFontSize}"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
StyleClass="box-row-button"
|
StyleClass="box-row-button"
|
||||||
Clicked="ClearExpirationDate_Clicked" />
|
Clicked="ClearExpirationDate_Clicked" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
@ -371,6 +396,7 @@
|
|||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
<Entry
|
<Entry
|
||||||
Text="{Binding MaxAccessCount}"
|
Text="{Binding MaxAccessCount}"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
StyleClass="box-value"
|
StyleClass="box-value"
|
||||||
Keyboard="Numeric"
|
Keyboard="Numeric"
|
||||||
MaxLength="9"
|
MaxLength="9"
|
||||||
@ -380,6 +406,7 @@
|
|||||||
x:Name="_maxAccessCountStepper"
|
x:Name="_maxAccessCountStepper"
|
||||||
Value="{Binding MaxAccessCount}"
|
Value="{Binding MaxAccessCount}"
|
||||||
Maximum="999999999"
|
Maximum="999999999"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
Margin="10,0,0,0" />
|
Margin="10,0,0,0" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<Label
|
<Label
|
||||||
@ -413,11 +440,13 @@
|
|||||||
<Entry
|
<Entry
|
||||||
Text="{Binding NewPassword}"
|
Text="{Binding NewPassword}"
|
||||||
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
|
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
StyleClass="box-value"
|
StyleClass="box-value"
|
||||||
IsSpellCheckEnabled="False"
|
IsSpellCheckEnabled="False"
|
||||||
IsTextPredictionEnabled="False"
|
IsTextPredictionEnabled="False"
|
||||||
HorizontalOptions="FillAndExpand" />
|
HorizontalOptions="FillAndExpand" />
|
||||||
<controls:FaButton
|
<controls:FaButton
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
StyleClass="box-row-button, box-row-button-platform"
|
StyleClass="box-row-button, box-row-button-platform"
|
||||||
Text="{Binding ShowPasswordIcon}"
|
Text="{Binding ShowPasswordIcon}"
|
||||||
Command="{Binding TogglePasswordCommand}"
|
Command="{Binding TogglePasswordCommand}"
|
||||||
@ -439,6 +468,7 @@
|
|||||||
<Editor
|
<Editor
|
||||||
AutoSize="TextChanges"
|
AutoSize="TextChanges"
|
||||||
Text="{Binding Send.Notes}"
|
Text="{Binding Send.Notes}"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
StyleClass="box-value"
|
StyleClass="box-value"
|
||||||
Margin="{Binding EditorMargins}" />
|
Margin="{Binding EditorMargins}" />
|
||||||
<BoxView
|
<BoxView
|
||||||
@ -459,6 +489,7 @@
|
|||||||
HorizontalOptions="StartAndExpand" />
|
HorizontalOptions="StartAndExpand" />
|
||||||
<Switch
|
<Switch
|
||||||
IsToggled="{Binding Send.Disabled}"
|
IsToggled="{Binding Send.Disabled}"
|
||||||
|
IsEnabled="{Binding SendEnabled}"
|
||||||
HorizontalOptions="End"
|
HorizontalOptions="End"
|
||||||
Margin="10,0,0,0" />
|
Margin="10,0,0,0" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
@ -27,7 +27,6 @@ namespace Bit.App.Pages
|
|||||||
_vm.Page = this;
|
_vm.Page = this;
|
||||||
_vm.SendId = sendId;
|
_vm.SendId = sendId;
|
||||||
_vm.Type = type;
|
_vm.Type = type;
|
||||||
_vm.Init();
|
|
||||||
SetActivityIndicator();
|
SetActivityIndicator();
|
||||||
if (Device.RuntimePlatform == Device.Android)
|
if (Device.RuntimePlatform == Device.Android)
|
||||||
{
|
{
|
||||||
@ -42,7 +41,7 @@ namespace Bit.App.Pages
|
|||||||
_vm.SegmentedButtonFontSize = 13;
|
_vm.SegmentedButtonFontSize = 13;
|
||||||
_vm.SegmentedButtonMargins = new Thickness(0, 10, 0, 0);
|
_vm.SegmentedButtonMargins = new Thickness(0, 10, 0, 0);
|
||||||
_vm.EditorMargins = new Thickness(0, 5, 0, 0);
|
_vm.EditorMargins = new Thickness(0, 5, 0, 0);
|
||||||
_btnOptions.WidthRequest = 62;
|
_btnOptions.WidthRequest = 70;
|
||||||
_btnOptionsDown.WidthRequest = 30;
|
_btnOptionsDown.WidthRequest = 30;
|
||||||
_btnOptionsUp.WidthRequest = 30;
|
_btnOptionsUp.WidthRequest = 30;
|
||||||
}
|
}
|
||||||
@ -75,6 +74,7 @@ namespace Bit.App.Pages
|
|||||||
protected override async void OnAppearing()
|
protected override async void OnAppearing()
|
||||||
{
|
{
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
|
await _vm.InitAsync();
|
||||||
_broadcasterService.Subscribe(nameof(SendAddEditPage), message =>
|
_broadcasterService.Subscribe(nameof(SendAddEditPage), message =>
|
||||||
{
|
{
|
||||||
if (message.Command == "selectFileResult")
|
if (message.Command == "selectFileResult")
|
||||||
@ -99,6 +99,7 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
RequestFocus(_nameEntry);
|
RequestFocus(_nameEntry);
|
||||||
}
|
}
|
||||||
|
AdjustToolbar();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,9 +112,9 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TextType_Clicked(object sender, EventArgs eventArgs)
|
private async void TextType_Clicked(object sender, EventArgs eventArgs)
|
||||||
{
|
{
|
||||||
_vm.TypeChanged(SendType.Text);
|
await _vm.TypeChangedAsync(SendType.Text);
|
||||||
_nameEntry.ReturnType = ReturnType.Next;
|
_nameEntry.ReturnType = ReturnType.Next;
|
||||||
_nameEntry.ReturnCommand = new Command(() => _textEditor.Focus());
|
_nameEntry.ReturnCommand = new Command(() => _textEditor.Focus());
|
||||||
if (string.IsNullOrWhiteSpace(_vm.Send.Name))
|
if (string.IsNullOrWhiteSpace(_vm.Send.Name))
|
||||||
@ -122,9 +123,9 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FileType_Clicked(object sender, EventArgs eventArgs)
|
private async void FileType_Clicked(object sender, EventArgs eventArgs)
|
||||||
{
|
{
|
||||||
_vm.TypeChanged(SendType.File);
|
await _vm.TypeChangedAsync(SendType.File);
|
||||||
_nameEntry.ReturnType = ReturnType.Done;
|
_nameEntry.ReturnType = ReturnType.Done;
|
||||||
_nameEntry.ReturnCommand = null;
|
_nameEntry.ReturnCommand = null;
|
||||||
if (string.IsNullOrWhiteSpace(_vm.Send.Name))
|
if (string.IsNullOrWhiteSpace(_vm.Send.Name))
|
||||||
@ -219,12 +220,12 @@ namespace Bit.App.Pages
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var options = new List<string>();
|
var options = new List<string>();
|
||||||
if (_vm.Send.HasPassword)
|
if (_vm.SendEnabled && _vm.EditMode)
|
||||||
{
|
|
||||||
options.Add(AppResources.RemovePassword);
|
|
||||||
}
|
|
||||||
if (_vm.EditMode)
|
|
||||||
{
|
{
|
||||||
|
if (_vm.Send.HasPassword)
|
||||||
|
{
|
||||||
|
options.Add(AppResources.RemovePassword);
|
||||||
|
}
|
||||||
options.Add(AppResources.CopyLink);
|
options.Add(AppResources.CopyLink);
|
||||||
options.Add(AppResources.ShareLink);
|
options.Add(AppResources.ShareLink);
|
||||||
}
|
}
|
||||||
@ -259,5 +260,16 @@ namespace Bit.App.Pages
|
|||||||
await Navigation.PopModalAsync();
|
await Navigation.PopModalAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AdjustToolbar()
|
||||||
|
{
|
||||||
|
_saveItem.IsEnabled = _vm.SendEnabled;
|
||||||
|
if (!_vm.SendEnabled && _vm.EditMode && Device.RuntimePlatform == Device.Android)
|
||||||
|
{
|
||||||
|
ToolbarItems.Remove(_removePassword);
|
||||||
|
ToolbarItems.Remove(_copyLink);
|
||||||
|
ToolbarItems.Remove(_shareLink);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,9 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
private readonly IDeviceActionService _deviceActionService;
|
private readonly IDeviceActionService _deviceActionService;
|
||||||
private readonly IPlatformUtilsService _platformUtilsService;
|
private readonly IPlatformUtilsService _platformUtilsService;
|
||||||
|
private readonly IUserService _userService;
|
||||||
private readonly ISendService _sendService;
|
private readonly ISendService _sendService;
|
||||||
|
private bool _sendEnabled;
|
||||||
private bool _canAccessPremium;
|
private bool _canAccessPremium;
|
||||||
private SendView _send;
|
private SendView _send;
|
||||||
private string _fileName;
|
private string _fileName;
|
||||||
@ -42,6 +44,7 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||||
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
||||||
|
_userService = ServiceContainer.Resolve<IUserService>("userService");
|
||||||
_sendService = ServiceContainer.Resolve<ISendService>("sendService");
|
_sendService = ServiceContainer.Resolve<ISendService>("sendService");
|
||||||
TogglePasswordCommand = new Command(TogglePassword);
|
TogglePasswordCommand = new Command(TogglePassword);
|
||||||
|
|
||||||
@ -87,6 +90,11 @@ namespace Bit.App.Pages
|
|||||||
public List<KeyValuePair<string, SendType>> TypeOptions { get; }
|
public List<KeyValuePair<string, SendType>> TypeOptions { get; }
|
||||||
public List<KeyValuePair<string, string>> DeletionTypeOptions { get; }
|
public List<KeyValuePair<string, string>> DeletionTypeOptions { get; }
|
||||||
public List<KeyValuePair<string, string>> ExpirationTypeOptions { get; }
|
public List<KeyValuePair<string, string>> ExpirationTypeOptions { get; }
|
||||||
|
public bool SendEnabled
|
||||||
|
{
|
||||||
|
get => _sendEnabled;
|
||||||
|
set => SetProperty(ref _sendEnabled, value);
|
||||||
|
}
|
||||||
public int DeletionDateTypeSelectedIndex
|
public int DeletionDateTypeSelectedIndex
|
||||||
{
|
{
|
||||||
get => _deletionDateTypeSelectedIndex;
|
get => _deletionDateTypeSelectedIndex;
|
||||||
@ -189,16 +197,15 @@ namespace Bit.App.Pages
|
|||||||
public bool ShowExpirationCustomPickers => EditMode || ExpirationDateTypeSelectedIndex == 7;
|
public bool ShowExpirationCustomPickers => EditMode || ExpirationDateTypeSelectedIndex == 7;
|
||||||
public string ShowPasswordIcon => ShowPassword ? "" : "";
|
public string ShowPasswordIcon => ShowPassword ? "" : "";
|
||||||
|
|
||||||
public void Init()
|
public async Task InitAsync()
|
||||||
{
|
{
|
||||||
PageTitle = EditMode ? AppResources.EditSend : AppResources.AddSend;
|
PageTitle = EditMode ? AppResources.EditSend : AppResources.AddSend;
|
||||||
|
_canAccessPremium = await _userService.CanAccessPremiumAsync();
|
||||||
|
SendEnabled = ! await AppHelpers.IsSendDisabledByPolicyAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> LoadAsync()
|
public async Task<bool> LoadAsync()
|
||||||
{
|
{
|
||||||
var userService = ServiceContainer.Resolve<IUserService>("userService");
|
|
||||||
_canAccessPremium = await userService.CanAccessPremiumAsync();
|
|
||||||
// TODO Policy Check
|
|
||||||
if (Send == null)
|
if (Send == null)
|
||||||
{
|
{
|
||||||
_isOverridingPickers = true;
|
_isOverridingPickers = true;
|
||||||
@ -284,7 +291,7 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
public async Task<bool> SubmitAsync()
|
public async Task<bool> SubmitAsync()
|
||||||
{
|
{
|
||||||
if (Send == null)
|
if (Send == null || !SendEnabled)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -349,7 +356,7 @@ namespace Bit.App.Pages
|
|||||||
if (savedSend != null)
|
if (savedSend != null)
|
||||||
{
|
{
|
||||||
var savedSendView = await savedSend.DecryptAsync();
|
var savedSendView = await savedSend.DecryptAsync();
|
||||||
await AppHelpers.ShareSendUrl(savedSendView);
|
await AppHelpers.ShareSendUrlAsync(savedSendView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,14 +381,12 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
public async Task CopyLinkAsync()
|
public async Task CopyLinkAsync()
|
||||||
{
|
{
|
||||||
await _platformUtilsService.CopyToClipboardAsync(AppHelpers.GetSendUrl(Send));
|
await AppHelpers.CopySendUrlAsync(Send);
|
||||||
_platformUtilsService.ShowToast("info", null,
|
|
||||||
string.Format(AppResources.ValueHasBeenCopied, AppResources.ShareLink));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ShareLinkAsync()
|
public async Task ShareLinkAsync()
|
||||||
{
|
{
|
||||||
await AppHelpers.ShareSendUrl(Send);
|
await AppHelpers.ShareSendUrlAsync(Send);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> DeleteAsync()
|
public async Task<bool> DeleteAsync()
|
||||||
@ -389,7 +394,7 @@ namespace Bit.App.Pages
|
|||||||
return await AppHelpers.DeleteSendAsync(SendId);
|
return await AppHelpers.DeleteSendAsync(SendId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void TypeChanged(SendType type)
|
public async Task TypeChangedAsync(SendType type)
|
||||||
{
|
{
|
||||||
if (Send != null)
|
if (Send != null)
|
||||||
{
|
{
|
||||||
|
@ -37,7 +37,8 @@
|
|||||||
x:DataType="pages:SendGroupingsPageListItem">
|
x:DataType="pages:SendGroupingsPageListItem">
|
||||||
<controls:SendViewCell
|
<controls:SendViewCell
|
||||||
Send="{Binding Send}"
|
Send="{Binding Send}"
|
||||||
ButtonCommand="{Binding BindingContext.SendOptionsCommand, Source={x:Reference _page}}" />
|
ButtonCommand="{Binding BindingContext.SendOptionsCommand, Source={x:Reference _page}}"
|
||||||
|
ShowOptions="{Binding ShowOptions}" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate x:Key="sendGroupTemplate"
|
<DataTemplate x:Key="sendGroupTemplate"
|
||||||
@ -72,6 +73,20 @@
|
|||||||
GroupTemplate="{StaticResource sendGroupTemplate}" />
|
GroupTemplate="{StaticResource sendGroupTemplate}" />
|
||||||
|
|
||||||
<StackLayout x:Key="mainLayout" x:Name="_mainLayout">
|
<StackLayout x:Key="mainLayout" x:Name="_mainLayout">
|
||||||
|
<StackLayout StyleClass="box">
|
||||||
|
<Frame
|
||||||
|
IsVisible="{Binding SendEnabled, Converter={StaticResource inverseBool}}"
|
||||||
|
Padding="10"
|
||||||
|
Margin="0, 12, 0, 6"
|
||||||
|
HasShadow="False"
|
||||||
|
BackgroundColor="Transparent"
|
||||||
|
BorderColor="Accent">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n SendDisabledWarning}"
|
||||||
|
StyleClass="text-muted, text-sm, text-bold"
|
||||||
|
HorizontalTextAlignment="Center" />
|
||||||
|
</Frame>
|
||||||
|
</StackLayout>
|
||||||
<StackLayout
|
<StackLayout
|
||||||
VerticalOptions="CenterAndExpand"
|
VerticalOptions="CenterAndExpand"
|
||||||
Padding="20, 0"
|
Padding="20, 0"
|
||||||
@ -143,6 +158,7 @@
|
|||||||
<Button
|
<Button
|
||||||
x:Name="_fab"
|
x:Name="_fab"
|
||||||
Image="plus.png"
|
Image="plus.png"
|
||||||
|
IsVisible="{Binding SendEnabled}"
|
||||||
Clicked="AddButton_Clicked"
|
Clicked="AddButton_Clicked"
|
||||||
Style="{StaticResource btn-fab}"
|
Style="{StaticResource btn-fab}"
|
||||||
AbsoluteLayout.LayoutFlags="PositionProportional"
|
AbsoluteLayout.LayoutFlags="PositionProportional"
|
||||||
|
@ -55,9 +55,10 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
public ExtendedListView ListView { get; set; }
|
public ExtendedListView ListView { get; set; }
|
||||||
|
|
||||||
protected async override void OnAppearing()
|
protected override async void OnAppearing()
|
||||||
{
|
{
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
|
await _vm.InitAsync();
|
||||||
if (_syncService.SyncInProgress)
|
if (_syncService.SyncInProgress)
|
||||||
{
|
{
|
||||||
IsBusy = true;
|
IsBusy = true;
|
||||||
@ -107,6 +108,7 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
|
|
||||||
await ShowPreviousPageAsync();
|
await ShowPreviousPageAsync();
|
||||||
|
AdjustToolbar();
|
||||||
}, _mainContent);
|
}, _mainContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,5 +186,10 @@ namespace Bit.App.Pages
|
|||||||
}
|
}
|
||||||
_previousPage = null;
|
_previousPage = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AdjustToolbar()
|
||||||
|
{
|
||||||
|
_addItem.IsEnabled = _vm.SendEnabled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ namespace Bit.App.Pages
|
|||||||
public SendView Send { get; set; }
|
public SendView Send { get; set; }
|
||||||
public SendType? Type { get; set; }
|
public SendType? Type { get; set; }
|
||||||
public string ItemCount { get; set; }
|
public string ItemCount { get; set; }
|
||||||
|
public bool ShowOptions { get; set; }
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,7 @@ namespace Bit.App.Pages
|
|||||||
{
|
{
|
||||||
public class SendGroupingsPageViewModel : BaseViewModel
|
public class SendGroupingsPageViewModel : BaseViewModel
|
||||||
{
|
{
|
||||||
|
private bool _sendEnabled;
|
||||||
private bool _refreshing;
|
private bool _refreshing;
|
||||||
private bool _doingLoad;
|
private bool _doingLoad;
|
||||||
private bool _loading;
|
private bool _loading;
|
||||||
@ -65,6 +66,11 @@ namespace Bit.App.Pages
|
|||||||
public bool HasSends { get; set; }
|
public bool HasSends { get; set; }
|
||||||
public List<SendView> Sends { get; set; }
|
public List<SendView> Sends { get; set; }
|
||||||
|
|
||||||
|
public bool SendEnabled
|
||||||
|
{
|
||||||
|
get => _sendEnabled;
|
||||||
|
set => SetProperty(ref _sendEnabled, value);
|
||||||
|
}
|
||||||
public bool Refreshing
|
public bool Refreshing
|
||||||
{
|
{
|
||||||
get => _refreshing;
|
get => _refreshing;
|
||||||
@ -110,6 +116,11 @@ namespace Bit.App.Pages
|
|||||||
public Command<SendView> SendOptionsCommand { get; set; }
|
public Command<SendView> SendOptionsCommand { get; set; }
|
||||||
public bool LoadedOnce { get; set; }
|
public bool LoadedOnce { get; set; }
|
||||||
|
|
||||||
|
public async Task InitAsync()
|
||||||
|
{
|
||||||
|
SendEnabled = ! await AppHelpers.IsSendDisabledByPolicyAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task LoadAsync()
|
public async Task LoadAsync()
|
||||||
{
|
{
|
||||||
if (_doingLoad)
|
if (_doingLoad)
|
||||||
@ -167,7 +178,11 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
if (Sends?.Any() ?? false)
|
if (Sends?.Any() ?? false)
|
||||||
{
|
{
|
||||||
var sendsListItems = Sends.Select(s => new SendGroupingsPageListItem { Send = s }).ToList();
|
var sendsListItems = Sends.Select(s => new SendGroupingsPageListItem
|
||||||
|
{
|
||||||
|
Send = s,
|
||||||
|
ShowOptions = SendEnabled
|
||||||
|
}).ToList();
|
||||||
groupedSends.Add(new SendGroupingsPageListGroup(sendsListItems,
|
groupedSends.Add(new SendGroupingsPageListGroup(sendsListItems,
|
||||||
MainPage ? AppResources.AllSends : AppResources.Sends, sendsListItems.Count,
|
MainPage ? AppResources.AllSends : AppResources.Sends, sendsListItems.Count,
|
||||||
uppercaseGroupNames, !MainPage));
|
uppercaseGroupNames, !MainPage));
|
||||||
|
@ -72,7 +72,8 @@
|
|||||||
<DataTemplate x:DataType="views:SendView">
|
<DataTemplate x:DataType="views:SendView">
|
||||||
<controls:SendViewCell
|
<controls:SendViewCell
|
||||||
Send="{Binding .}"
|
Send="{Binding .}"
|
||||||
ButtonCommand="{Binding BindingContext.SendOptionsCommand, Source={x:Reference _page}}" />
|
ButtonCommand="{Binding BindingContext.SendOptionsCommand, Source={x:Reference _page}}"
|
||||||
|
ShowOptions="{Binding BindingContext.SendEnabled, Source={x:Reference _page}}" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListView.ItemTemplate>
|
</ListView.ItemTemplate>
|
||||||
</ListView>
|
</ListView>
|
||||||
|
@ -15,6 +15,7 @@ namespace Bit.App.Pages
|
|||||||
private readonly ISearchService _searchService;
|
private readonly ISearchService _searchService;
|
||||||
|
|
||||||
private CancellationTokenSource _searchCancellationTokenSource;
|
private CancellationTokenSource _searchCancellationTokenSource;
|
||||||
|
private bool _sendEnabled;
|
||||||
private bool _showNoData;
|
private bool _showNoData;
|
||||||
private bool _showList;
|
private bool _showList;
|
||||||
|
|
||||||
@ -29,6 +30,12 @@ namespace Bit.App.Pages
|
|||||||
public ExtendedObservableCollection<SendView> Sends { get; set; }
|
public ExtendedObservableCollection<SendView> Sends { get; set; }
|
||||||
public Func<SendView, bool> Filter { get; set; }
|
public Func<SendView, bool> Filter { get; set; }
|
||||||
|
|
||||||
|
public bool SendEnabled
|
||||||
|
{
|
||||||
|
get => _sendEnabled;
|
||||||
|
set => SetProperty(ref _sendEnabled, value);
|
||||||
|
}
|
||||||
|
|
||||||
public bool ShowNoData
|
public bool ShowNoData
|
||||||
{
|
{
|
||||||
get => _showNoData;
|
get => _showNoData;
|
||||||
@ -51,6 +58,7 @@ namespace Bit.App.Pages
|
|||||||
|
|
||||||
public async Task InitAsync()
|
public async Task InitAsync()
|
||||||
{
|
{
|
||||||
|
SendEnabled = ! await AppHelpers.IsSendDisabledByPolicyAsync();
|
||||||
if (!string.IsNullOrWhiteSpace((Page as SendsPage).SearchBar.Text))
|
if (!string.IsNullOrWhiteSpace((Page as SendsPage).SearchBar.Text))
|
||||||
{
|
{
|
||||||
Search((Page as SendsPage).SearchBar.Text, 200);
|
Search((Page as SendsPage).SearchBar.Text, 200);
|
||||||
|
12
src/App/Resources/AppResources.Designer.cs
generated
12
src/App/Resources/AppResources.Designer.cs
generated
@ -3375,6 +3375,12 @@ namespace Bit.App.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string SendLink {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("SendLink", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string SearchSends {
|
public static string SearchSends {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("SearchSends", resourceCulture);
|
return ResourceManager.GetString("SearchSends", resourceCulture);
|
||||||
@ -3458,5 +3464,11 @@ namespace Bit.App.Resources {
|
|||||||
return ResourceManager.GetString("ShareOnSave", resourceCulture);
|
return ResourceManager.GetString("ShareOnSave", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string SendDisabledWarning {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("SendDisabledWarning", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1907,8 +1907,12 @@
|
|||||||
<data name="ShareLink" xml:space="preserve">
|
<data name="ShareLink" xml:space="preserve">
|
||||||
<value>Share Link</value>
|
<value>Share Link</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SendLink" xml:space="preserve">
|
||||||
|
<value>Send link</value>
|
||||||
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
|
</data>
|
||||||
<data name="SearchSends" xml:space="preserve">
|
<data name="SearchSends" xml:space="preserve">
|
||||||
<value>Search sends</value>
|
<value>Search Sends</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditSend" xml:space="preserve">
|
<data name="EditSend" xml:space="preserve">
|
||||||
@ -1957,4 +1961,8 @@
|
|||||||
<value>Share this Send upon save.</value>
|
<value>Share this Send upon save.</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SendDisabledWarning" xml:space="preserve">
|
||||||
|
<value>Due to an enterprise policy, you are only able to delete an existing Send.</value>
|
||||||
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
@ -10,6 +10,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Bit.App.Models;
|
using Bit.App.Models;
|
||||||
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
using Xamarin.Essentials;
|
using Xamarin.Essentials;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
@ -157,13 +158,11 @@ namespace Bit.App.Utilities
|
|||||||
}
|
}
|
||||||
else if (selection == AppResources.CopyLink)
|
else if (selection == AppResources.CopyLink)
|
||||||
{
|
{
|
||||||
await platformUtilsService.CopyToClipboardAsync(GetSendUrl(send));
|
await CopySendUrlAsync(send);
|
||||||
platformUtilsService.ShowToast("info", null,
|
|
||||||
string.Format(AppResources.ValueHasBeenCopied, AppResources.ShareLink));
|
|
||||||
}
|
}
|
||||||
else if (selection == AppResources.ShareLink)
|
else if (selection == AppResources.ShareLink)
|
||||||
{
|
{
|
||||||
await ShareSendUrl(send);
|
await ShareSendUrlAsync(send);
|
||||||
}
|
}
|
||||||
else if (selection == AppResources.RemovePassword)
|
else if (selection == AppResources.RemovePassword)
|
||||||
{
|
{
|
||||||
@ -176,14 +175,24 @@ namespace Bit.App.Utilities
|
|||||||
return selection;
|
return selection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetSendUrl(SendView send)
|
public static async Task CopySendUrlAsync(SendView send)
|
||||||
{
|
{
|
||||||
var environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
if (await IsSendDisabledByPolicyAsync())
|
||||||
return environmentService.BaseUrl + "/#/send/" + send.AccessId + "/" + send.UrlB64Key;
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
||||||
|
await platformUtilsService.CopyToClipboardAsync(AppHelpers.GetSendUrl(send));
|
||||||
|
platformUtilsService.ShowToast("info", null,
|
||||||
|
string.Format(AppResources.ValueHasBeenCopied, AppResources.SendLink));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task ShareSendUrl(SendView send)
|
public static async Task ShareSendUrlAsync(SendView send)
|
||||||
{
|
{
|
||||||
|
if (await IsSendDisabledByPolicyAsync())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
await Share.RequestAsync(new ShareTextRequest
|
await Share.RequestAsync(new ShareTextRequest
|
||||||
{
|
{
|
||||||
Uri = new Uri(GetSendUrl(send)).ToString(),
|
Uri = new Uri(GetSendUrl(send)).ToString(),
|
||||||
@ -191,9 +200,19 @@ namespace Bit.App.Utilities
|
|||||||
Subject = send.Name
|
Subject = send.Name
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetSendUrl(SendView send)
|
||||||
|
{
|
||||||
|
var environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
||||||
|
return environmentService.BaseUrl + "/#/send/" + send.AccessId + "/" + send.UrlB64Key;
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<bool> RemoveSendPasswordAsync(string sendId)
|
public static async Task<bool> RemoveSendPasswordAsync(string sendId)
|
||||||
{
|
{
|
||||||
|
if (await IsSendDisabledByPolicyAsync())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
var platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
||||||
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
var deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||||
var sendService = ServiceContainer.Resolve<ISendService>("sendService");
|
var sendService = ServiceContainer.Resolve<ISendService>("sendService");
|
||||||
@ -270,6 +289,23 @@ namespace Bit.App.Utilities
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<bool> IsSendDisabledByPolicyAsync()
|
||||||
|
{
|
||||||
|
var policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
|
||||||
|
var userService = ServiceContainer.Resolve<IUserService>("userService");
|
||||||
|
|
||||||
|
var policies = await policyService.GetAll(PolicyType.DisableSend);
|
||||||
|
var organizations = await userService.GetAllOrganizationAsync();
|
||||||
|
return organizations.Any(o =>
|
||||||
|
{
|
||||||
|
return o.Enabled &&
|
||||||
|
o.Status == OrganizationUserStatusType.Confirmed &&
|
||||||
|
o.UsePolicies &&
|
||||||
|
!o.canManagePolicies &&
|
||||||
|
policies.Any(p => p.OrganizationId == o.Id && p.Enabled);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<bool> PerformUpdateTasksAsync(ISyncService syncService,
|
public static async Task<bool> PerformUpdateTasksAsync(ISyncService syncService,
|
||||||
IDeviceActionService deviceActionService, IStorageService storageService)
|
IDeviceActionService deviceActionService, IStorageService storageService)
|
||||||
{
|
{
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
{
|
{
|
||||||
public enum PolicyType : byte
|
public enum PolicyType : byte
|
||||||
{
|
{
|
||||||
TwoFactorAuthentication = 0,
|
TwoFactorAuthentication = 0, // Requires users to have 2fa enabled
|
||||||
MasterPassword = 1,
|
MasterPassword = 1, // Sets minimum requirements for master password complexity
|
||||||
PasswordGenerator = 2,
|
PasswordGenerator = 2, // Sets minimum requirements/default type for generated passwords/passphrases
|
||||||
OnlyOrg = 3,
|
OnlyOrg = 3, // Allows users to only be apart of one organization
|
||||||
RequireSso = 4,
|
RequireSso = 4, // Requires users to authenticate with SSO
|
||||||
PersonalOwnership = 5,
|
PersonalOwnership = 5, // Disables personal vault ownership for adding/cloning items
|
||||||
|
DisableSend = 6, // Disables the ability to create and edit Sends
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user