1
0
mirror of https://github.com/bitwarden/mobile synced 2026-01-07 19:13:19 +00: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:
Matt Portune
2021-02-18 16:58:20 -05:00
committed by GitHub
parent 20d5c6a63a
commit 3799eb4603
18 changed files with 235 additions and 42 deletions

View File

@@ -14,7 +14,8 @@
</ContentPage.BindingContext>
<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.Resources>
@@ -76,6 +77,18 @@
<ScrollView x:Key="scrollView" x:Name="_scrollView">
<StackLayout Spacing="20">
<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">
<Label
Text="{u:I18n Name}"
@@ -83,6 +96,7 @@
<Entry
x:Name="_nameEntry"
Text="{Binding Send.Name}"
IsEnabled="{Binding SendEnabled}"
StyleClass="box-value" />
<Label
Text="{u:I18n NameInfo}"
@@ -186,6 +200,7 @@
HorizontalTextAlignment="Center" />
<Button
Text="{u:I18n ChooseFile}"
IsEnabled="{Binding SendEnabled}"
StyleClass="box-button-row"
Clicked="ChooseFile_Clicked" />
<Label
@@ -210,6 +225,7 @@
x:Name="_textEditor"
AutoSize="TextChanges"
Text="{Binding Send.Text.Text}"
IsEnabled="{Binding SendEnabled}"
StyleClass="box-value"
Margin="{Binding EditorMargins}" />
<BoxView
@@ -229,6 +245,7 @@
HorizontalOptions="StartAndExpand" />
<Switch
IsToggled="{Binding Send.Text.Hidden}"
IsEnabled="{Binding SendEnabled}"
HorizontalOptions="End"
Margin="10,0,0,0" />
</StackLayout>
@@ -241,6 +258,7 @@
HorizontalOptions="StartAndExpand" />
<Switch
IsToggled="{Binding ShareOnSave}"
IsEnabled="{Binding SendEnabled}"
HorizontalOptions="End"
Margin="10,0,0,0" />
</StackLayout>
@@ -281,6 +299,7 @@
IsVisible="{Binding EditMode, Converter={StaticResource inverseBool}}"
ItemsSource="{Binding DeletionTypeOptions, Mode=OneTime}"
SelectedIndex="{Binding DeletionDateTypeSelectedIndex}"
IsEnabled="{Binding SendEnabled}"
StyleClass="box-value"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n DeletionTime}" />
@@ -294,12 +313,14 @@
<controls:ExtendedDatePicker
NullableDate="{Binding DeletionDate, Mode=TwoWay}"
Format="d"
IsEnabled="{Binding SendEnabled}"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n DeletionDate}"
Grid.Column="0" />
<controls:ExtendedTimePicker
NullableTime="{Binding DeletionTime, Mode=TwoWay}"
Format="t"
IsEnabled="{Binding SendEnabled}"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n DeletionTime}"
Grid.Column="1" />
@@ -318,6 +339,7 @@
IsVisible="{Binding EditMode, Converter={StaticResource inverseBool}}"
ItemsSource="{Binding ExpirationTypeOptions, Mode=OneTime}"
SelectedIndex="{Binding ExpirationDateTypeSelectedIndex}"
IsEnabled="{Binding SendEnabled}"
StyleClass="box-value"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n ExpirationTime}" />
@@ -332,6 +354,7 @@
NullableDate="{Binding ExpirationDate, Mode=TwoWay}"
PlaceHolder="mm/dd/yyyy"
Format="d"
IsEnabled="{Binding SendEnabled}"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n ExpirationDate}"
Grid.Column="0" />
@@ -339,6 +362,7 @@
NullableTime="{Binding ExpirationTime, Mode=TwoWay}"
PlaceHolder="--:-- --"
Format="t"
IsEnabled="{Binding SendEnabled}"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n ExpirationTime}"
Grid.Column="1" />
@@ -356,6 +380,7 @@
WidthRequest="110"
HeightRequest="{Binding SegmentedButtonHeight}"
FontSize="{Binding SegmentedButtonFontSize}"
IsEnabled="{Binding SendEnabled}"
StyleClass="box-row-button"
Clicked="ClearExpirationDate_Clicked" />
</StackLayout>
@@ -371,6 +396,7 @@
Orientation="Horizontal">
<Entry
Text="{Binding MaxAccessCount}"
IsEnabled="{Binding SendEnabled}"
StyleClass="box-value"
Keyboard="Numeric"
MaxLength="9"
@@ -380,6 +406,7 @@
x:Name="_maxAccessCountStepper"
Value="{Binding MaxAccessCount}"
Maximum="999999999"
IsEnabled="{Binding SendEnabled}"
Margin="10,0,0,0" />
</StackLayout>
<Label
@@ -413,11 +440,13 @@
<Entry
Text="{Binding NewPassword}"
IsPassword="{Binding ShowPassword, Converter={StaticResource inverseBool}}"
IsEnabled="{Binding SendEnabled}"
StyleClass="box-value"
IsSpellCheckEnabled="False"
IsTextPredictionEnabled="False"
HorizontalOptions="FillAndExpand" />
<controls:FaButton
IsEnabled="{Binding SendEnabled}"
StyleClass="box-row-button, box-row-button-platform"
Text="{Binding ShowPasswordIcon}"
Command="{Binding TogglePasswordCommand}"
@@ -439,6 +468,7 @@
<Editor
AutoSize="TextChanges"
Text="{Binding Send.Notes}"
IsEnabled="{Binding SendEnabled}"
StyleClass="box-value"
Margin="{Binding EditorMargins}" />
<BoxView
@@ -459,6 +489,7 @@
HorizontalOptions="StartAndExpand" />
<Switch
IsToggled="{Binding Send.Disabled}"
IsEnabled="{Binding SendEnabled}"
HorizontalOptions="End"
Margin="10,0,0,0" />
</StackLayout>

View File

@@ -27,7 +27,6 @@ namespace Bit.App.Pages
_vm.Page = this;
_vm.SendId = sendId;
_vm.Type = type;
_vm.Init();
SetActivityIndicator();
if (Device.RuntimePlatform == Device.Android)
{
@@ -42,7 +41,7 @@ namespace Bit.App.Pages
_vm.SegmentedButtonFontSize = 13;
_vm.SegmentedButtonMargins = new Thickness(0, 10, 0, 0);
_vm.EditorMargins = new Thickness(0, 5, 0, 0);
_btnOptions.WidthRequest = 62;
_btnOptions.WidthRequest = 70;
_btnOptionsDown.WidthRequest = 30;
_btnOptionsUp.WidthRequest = 30;
}
@@ -75,6 +74,7 @@ namespace Bit.App.Pages
protected override async void OnAppearing()
{
base.OnAppearing();
await _vm.InitAsync();
_broadcasterService.Subscribe(nameof(SendAddEditPage), message =>
{
if (message.Command == "selectFileResult")
@@ -99,6 +99,7 @@ namespace Bit.App.Pages
{
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.ReturnCommand = new Command(() => _textEditor.Focus());
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.ReturnCommand = null;
if (string.IsNullOrWhiteSpace(_vm.Send.Name))
@@ -219,12 +220,12 @@ namespace Bit.App.Pages
return;
}
var options = new List<string>();
if (_vm.Send.HasPassword)
{
options.Add(AppResources.RemovePassword);
}
if (_vm.EditMode)
if (_vm.SendEnabled && _vm.EditMode)
{
if (_vm.Send.HasPassword)
{
options.Add(AppResources.RemovePassword);
}
options.Add(AppResources.CopyLink);
options.Add(AppResources.ShareLink);
}
@@ -259,5 +260,16 @@ namespace Bit.App.Pages
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);
}
}
}
}

View File

@@ -18,7 +18,9 @@ namespace Bit.App.Pages
{
private readonly IDeviceActionService _deviceActionService;
private readonly IPlatformUtilsService _platformUtilsService;
private readonly IUserService _userService;
private readonly ISendService _sendService;
private bool _sendEnabled;
private bool _canAccessPremium;
private SendView _send;
private string _fileName;
@@ -42,6 +44,7 @@ namespace Bit.App.Pages
{
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
_userService = ServiceContainer.Resolve<IUserService>("userService");
_sendService = ServiceContainer.Resolve<ISendService>("sendService");
TogglePasswordCommand = new Command(TogglePassword);
@@ -87,6 +90,11 @@ namespace Bit.App.Pages
public List<KeyValuePair<string, SendType>> TypeOptions { get; }
public List<KeyValuePair<string, string>> DeletionTypeOptions { get; }
public List<KeyValuePair<string, string>> ExpirationTypeOptions { get; }
public bool SendEnabled
{
get => _sendEnabled;
set => SetProperty(ref _sendEnabled, value);
}
public int DeletionDateTypeSelectedIndex
{
get => _deletionDateTypeSelectedIndex;
@@ -189,16 +197,15 @@ namespace Bit.App.Pages
public bool ShowExpirationCustomPickers => EditMode || ExpirationDateTypeSelectedIndex == 7;
public string ShowPasswordIcon => ShowPassword ? "" : "";
public void Init()
public async Task InitAsync()
{
PageTitle = EditMode ? AppResources.EditSend : AppResources.AddSend;
_canAccessPremium = await _userService.CanAccessPremiumAsync();
SendEnabled = ! await AppHelpers.IsSendDisabledByPolicyAsync();
}
public async Task<bool> LoadAsync()
{
var userService = ServiceContainer.Resolve<IUserService>("userService");
_canAccessPremium = await userService.CanAccessPremiumAsync();
// TODO Policy Check
if (Send == null)
{
_isOverridingPickers = true;
@@ -284,7 +291,7 @@ namespace Bit.App.Pages
public async Task<bool> SubmitAsync()
{
if (Send == null)
if (Send == null || !SendEnabled)
{
return false;
}
@@ -349,7 +356,7 @@ namespace Bit.App.Pages
if (savedSend != null)
{
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()
{
await _platformUtilsService.CopyToClipboardAsync(AppHelpers.GetSendUrl(Send));
_platformUtilsService.ShowToast("info", null,
string.Format(AppResources.ValueHasBeenCopied, AppResources.ShareLink));
await AppHelpers.CopySendUrlAsync(Send);
}
public async Task ShareLinkAsync()
{
await AppHelpers.ShareSendUrl(Send);
await AppHelpers.ShareSendUrlAsync(Send);
}
public async Task<bool> DeleteAsync()
@@ -389,7 +394,7 @@ namespace Bit.App.Pages
return await AppHelpers.DeleteSendAsync(SendId);
}
public async void TypeChanged(SendType type)
public async Task TypeChangedAsync(SendType type)
{
if (Send != null)
{

View File

@@ -37,7 +37,8 @@
x:DataType="pages:SendGroupingsPageListItem">
<controls:SendViewCell
Send="{Binding Send}"
ButtonCommand="{Binding BindingContext.SendOptionsCommand, Source={x:Reference _page}}" />
ButtonCommand="{Binding BindingContext.SendOptionsCommand, Source={x:Reference _page}}"
ShowOptions="{Binding ShowOptions}" />
</DataTemplate>
<DataTemplate x:Key="sendGroupTemplate"
@@ -72,6 +73,20 @@
GroupTemplate="{StaticResource sendGroupTemplate}" />
<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
VerticalOptions="CenterAndExpand"
Padding="20, 0"
@@ -143,6 +158,7 @@
<Button
x:Name="_fab"
Image="plus.png"
IsVisible="{Binding SendEnabled}"
Clicked="AddButton_Clicked"
Style="{StaticResource btn-fab}"
AbsoluteLayout.LayoutFlags="PositionProportional"

View File

@@ -55,9 +55,10 @@ namespace Bit.App.Pages
public ExtendedListView ListView { get; set; }
protected async override void OnAppearing()
protected override async void OnAppearing()
{
base.OnAppearing();
await _vm.InitAsync();
if (_syncService.SyncInProgress)
{
IsBusy = true;
@@ -107,6 +108,7 @@ namespace Bit.App.Pages
}
await ShowPreviousPageAsync();
AdjustToolbar();
}, _mainContent);
}
@@ -184,5 +186,10 @@ namespace Bit.App.Pages
}
_previousPage = null;
}
private void AdjustToolbar()
{
_addItem.IsEnabled = _vm.SendEnabled;
}
}
}

View File

@@ -12,6 +12,7 @@ namespace Bit.App.Pages
public SendView Send { get; set; }
public SendType? Type { get; set; }
public string ItemCount { get; set; }
public bool ShowOptions { get; set; }
public string Name
{

View File

@@ -18,6 +18,7 @@ namespace Bit.App.Pages
{
public class SendGroupingsPageViewModel : BaseViewModel
{
private bool _sendEnabled;
private bool _refreshing;
private bool _doingLoad;
private bool _loading;
@@ -65,6 +66,11 @@ namespace Bit.App.Pages
public bool HasSends { get; set; }
public List<SendView> Sends { get; set; }
public bool SendEnabled
{
get => _sendEnabled;
set => SetProperty(ref _sendEnabled, value);
}
public bool Refreshing
{
get => _refreshing;
@@ -110,6 +116,11 @@ namespace Bit.App.Pages
public Command<SendView> SendOptionsCommand { get; set; }
public bool LoadedOnce { get; set; }
public async Task InitAsync()
{
SendEnabled = ! await AppHelpers.IsSendDisabledByPolicyAsync();
}
public async Task LoadAsync()
{
if (_doingLoad)
@@ -167,7 +178,11 @@ namespace Bit.App.Pages
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,
MainPage ? AppResources.AllSends : AppResources.Sends, sendsListItems.Count,
uppercaseGroupNames, !MainPage));

View File

@@ -72,7 +72,8 @@
<DataTemplate x:DataType="views:SendView">
<controls:SendViewCell
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>
</ListView.ItemTemplate>
</ListView>

View File

@@ -15,6 +15,7 @@ namespace Bit.App.Pages
private readonly ISearchService _searchService;
private CancellationTokenSource _searchCancellationTokenSource;
private bool _sendEnabled;
private bool _showNoData;
private bool _showList;
@@ -29,6 +30,12 @@ namespace Bit.App.Pages
public ExtendedObservableCollection<SendView> Sends { get; set; }
public Func<SendView, bool> Filter { get; set; }
public bool SendEnabled
{
get => _sendEnabled;
set => SetProperty(ref _sendEnabled, value);
}
public bool ShowNoData
{
get => _showNoData;
@@ -51,6 +58,7 @@ namespace Bit.App.Pages
public async Task InitAsync()
{
SendEnabled = ! await AppHelpers.IsSendDisabledByPolicyAsync();
if (!string.IsNullOrWhiteSpace((Page as SendsPage).SearchBar.Text))
{
Search((Page as SendsPage).SearchBar.Text, 200);