bitwarden-android/src/App/Pages/Vault/VaultAttachmentsPage.cs

326 lines
12 KiB
C#
Raw Normal View History

2017-07-22 22:38:08 +03:00
using System;
using System.Linq;
using Bit.App.Abstractions;
using Bit.App.Controls;
using Bit.App.Models.Page;
using Bit.App.Resources;
using Xamarin.Forms;
using XLabs.Ioc;
using Bit.App.Utilities;
using Plugin.Connectivity.Abstractions;
using Bit.App.Models;
using System.Threading.Tasks;
namespace Bit.App.Pages
{
public class VaultAttachmentsPage : ExtendedContentPage
{
private readonly ICipherService _cipherService;
2017-07-22 22:38:08 +03:00
private readonly IConnectivity _connectivity;
2017-12-22 23:00:11 +03:00
private readonly IDeviceActionService _deviceActionService;
2017-07-22 22:38:08 +03:00
private readonly IGoogleAnalyticsService _googleAnalyticsService;
2017-07-24 17:34:22 +03:00
private readonly ITokenService _tokenService;
private readonly ICryptoService _cryptoService;
private readonly string _cipherId;
private Cipher _cipher;
2017-07-22 22:38:08 +03:00
private byte[] _fileBytes;
private DateTime? _lastAction;
2017-07-24 17:34:22 +03:00
private bool _canUseAttachments = true;
2017-07-22 22:38:08 +03:00
public VaultAttachmentsPage(string cipherId)
2017-07-22 22:38:08 +03:00
: base(true)
{
_cipherId = cipherId;
_cipherService = Resolver.Resolve<ICipherService>();
2017-07-22 22:38:08 +03:00
_connectivity = Resolver.Resolve<IConnectivity>();
2017-12-22 23:00:11 +03:00
_deviceActionService = Resolver.Resolve<IDeviceActionService>();
2017-07-22 22:38:08 +03:00
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
2017-07-24 17:34:22 +03:00
_tokenService = Resolver.Resolve<ITokenService>();
_cryptoService = Resolver.Resolve<ICryptoService>();
2017-07-22 22:38:08 +03:00
Init();
}
public ExtendedObservableCollection<VaultAttachmentsPageModel.Attachment> PresentationAttchments { get; private set; }
= new ExtendedObservableCollection<VaultAttachmentsPageModel.Attachment>();
public ExtendedListView ListView { get; set; }
2018-01-03 20:18:15 +03:00
public RedrawableStackLayout NoDataStackLayout { get; set; }
2017-07-22 22:38:08 +03:00
public StackLayout AddNewStackLayout { get; set; }
public Label FileLabel { get; set; }
public ExtendedTableView NewTable { get; set; }
public Label NoDataLabel { get; set; }
private void Init()
{
2017-07-24 17:34:22 +03:00
_canUseAttachments = _cryptoService.EncKey != null;
2017-07-22 22:38:08 +03:00
SubscribeFileResult(true);
var selectButton = new ExtendedButton
{
Text = AppResources.ChooseFile,
2017-12-22 23:00:11 +03:00
Command = new Command(async () => await _deviceActionService.SelectFileAsync()),
2017-07-22 22:38:08 +03:00
Style = (Style)Application.Current.Resources["btn-primaryAccent"],
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Button))
};
FileLabel = new Label
{
Text = AppResources.NoFileChosen,
Style = (Style)Application.Current.Resources["text-muted"],
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
HorizontalTextAlignment = TextAlignment.Center
};
AddNewStackLayout = new StackLayout
{
Children = { selectButton, FileLabel },
Orientation = StackOrientation.Vertical,
Padding = new Thickness(20, Helpers.OnPlatform(iOS: 10, Android: 20), 20, 20),
VerticalOptions = LayoutOptions.Start
};
NewTable = new ExtendedTableView
{
Intent = TableIntent.Settings,
HasUnevenRows = true,
NoFooter = true,
EnableScrolling = false,
EnableSelection = false,
VerticalOptions = LayoutOptions.Start,
Margin = new Thickness(0, Helpers.OnPlatform(iOS: 10, Android: 30), 0, 0),
2018-01-03 20:18:15 +03:00
WrappingStackLayout = () => NoDataStackLayout,
2017-07-22 22:38:08 +03:00
Root = new TableRoot
{
new TableSection(AppResources.AddNewAttachment)
{
new ExtendedViewCell
{
View = AddNewStackLayout,
BackgroundColor = Color.White
}
}
}
};
ListView = new ExtendedListView(ListViewCachingStrategy.RecycleElement)
2017-07-22 22:38:08 +03:00
{
ItemsSource = PresentationAttchments,
HasUnevenRows = true,
ItemTemplate = new DataTemplate(() => new VaultAttachmentsViewCell()),
VerticalOptions = LayoutOptions.FillAndExpand
};
2017-07-24 17:34:22 +03:00
if(_tokenService.TokenPremium)
{
ListView.Footer = NewTable;
}
2017-07-22 22:38:08 +03:00
NoDataLabel = new Label
{
Text = AppResources.NoAttachments,
HorizontalTextAlignment = TextAlignment.Center,
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
Style = (Style)Application.Current.Resources["text-muted"]
};
2018-01-03 20:18:15 +03:00
NoDataStackLayout = new RedrawableStackLayout
2017-07-22 22:38:08 +03:00
{
VerticalOptions = LayoutOptions.Start,
Spacing = 0,
Margin = new Thickness(0, 40, 0, 0)
};
var saveToolBarItem = new ToolbarItem(AppResources.Save, Helpers.ToolbarImage("envelope.png"), async () =>
2017-07-22 22:38:08 +03:00
{
if(_lastAction.LastActionWasRecent() || _cipher == null)
2017-07-22 22:38:08 +03:00
{
return;
}
_lastAction = DateTime.UtcNow;
2017-07-24 17:34:22 +03:00
if(!_canUseAttachments)
{
await ShowUpdateKeyAsync();
return;
}
2017-07-22 22:38:08 +03:00
if(!_connectivity.IsConnected)
{
AlertNoConnection();
return;
}
if(_fileBytes == null)
{
await DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired,
AppResources.File), AppResources.Ok);
return;
}
_deviceActionService.ShowLoading(AppResources.Saving);
var saveTask = await _cipherService.EncryptAndSaveAttachmentAsync(_cipher, _fileBytes, FileLabel.Text);
_deviceActionService.HideLoading();
2017-07-22 22:38:08 +03:00
if(saveTask.Succeeded)
{
_fileBytes = null;
FileLabel.Text = AppResources.NoFileChosen;
2017-12-22 23:00:11 +03:00
_deviceActionService.Toast(AppResources.AttachementAdded);
2017-07-22 22:38:08 +03:00
_googleAnalyticsService.TrackAppEvent("AddedAttachment");
await LoadAttachmentsAsync();
}
else if(saveTask.Errors.Count() > 0)
{
await DisplayAlert(AppResources.AnErrorHasOccurred, saveTask.Errors.First().Message, AppResources.Ok);
2017-07-22 22:38:08 +03:00
}
else
{
await DisplayAlert(null, AppResources.AnErrorHasOccurred, AppResources.Ok);
2017-07-22 22:38:08 +03:00
}
}, ToolbarItemOrder.Default, 0);
Title = AppResources.Attachments;
Content = ListView;
2017-07-24 17:34:22 +03:00
if(_tokenService.TokenPremium)
{
ToolbarItems.Add(saveToolBarItem);
}
2017-07-22 22:38:08 +03:00
if(Device.RuntimePlatform == Device.iOS)
2017-07-22 22:38:08 +03:00
{
ListView.RowHeight = -1;
NewTable.RowHeight = -1;
NewTable.EstimatedRowHeight = 44;
NewTable.HeightRequest = 180;
ListView.BackgroundColor = Color.Transparent;
ToolbarItems.Add(new DismissModalToolBarItem(this, AppResources.Close));
}
else if(Device.RuntimePlatform == Device.Android)
{
ListView.BottomPadding = 50;
}
2017-07-22 22:38:08 +03:00
}
protected async override void OnAppearing()
{
base.OnAppearing();
ListView.ItemSelected += AttachmentSelected;
await LoadAttachmentsAsync();
2017-07-24 17:34:22 +03:00
if(_tokenService.TokenPremium && !_canUseAttachments)
{
await ShowUpdateKeyAsync();
}
2017-07-22 22:38:08 +03:00
}
protected override void OnDisappearing()
{
base.OnDisappearing();
ListView.ItemSelected -= AttachmentSelected;
}
private async Task LoadAttachmentsAsync()
{
_cipher = await _cipherService.GetByIdAsync(_cipherId);
if(_cipher == null)
2017-07-22 22:38:08 +03:00
{
await Navigation.PopForDeviceAsync();
return;
}
var attachmentsToAdd = _cipher.Attachments
2017-07-22 22:38:08 +03:00
.Select(a => new VaultAttachmentsPageModel.Attachment(a))
.OrderBy(s => s.Name);
PresentationAttchments.ResetWithRange(attachmentsToAdd);
AdjustContent();
}
private void AdjustContent()
{
if(PresentationAttchments.Count == 0)
{
NoDataStackLayout.Children.Clear();
NoDataStackLayout.Children.Add(NoDataLabel);
NoDataStackLayout.Children.Add(NewTable);
Content = NoDataStackLayout;
}
else
{
Content = ListView;
}
}
private async void AttachmentSelected(object sender, SelectedItemChangedEventArgs e)
{
var attachment = e.SelectedItem as VaultAttachmentsPageModel.Attachment;
if(attachment == null)
{
return;
}
((ListView)sender).SelectedItem = null;
var confirmed = await DisplayAlert(null, AppResources.DoYouReallyWantToDelete, AppResources.Yes,
AppResources.No);
if(!confirmed)
2017-07-22 22:38:08 +03:00
{
2017-07-24 17:34:22 +03:00
return;
}
2017-07-22 22:38:08 +03:00
_deviceActionService.ShowLoading(AppResources.Deleting);
var saveTask = await _cipherService.DeleteAttachmentAsync(_cipher, attachment.Id);
_deviceActionService.HideLoading();
2017-07-24 17:34:22 +03:00
if(saveTask.Succeeded)
{
2017-12-22 23:00:11 +03:00
_deviceActionService.Toast(AppResources.AttachmentDeleted);
2017-07-24 17:34:22 +03:00
_googleAnalyticsService.TrackAppEvent("DeletedAttachment");
await LoadAttachmentsAsync();
}
else if(saveTask.Errors.Count() > 0)
{
await DisplayAlert(AppResources.AnErrorHasOccurred, saveTask.Errors.First().Message, AppResources.Ok);
2017-07-24 17:34:22 +03:00
}
else
{
await DisplayAlert(null, AppResources.AnErrorHasOccurred, AppResources.Ok);
2017-07-22 22:38:08 +03:00
}
}
private void AlertNoConnection()
{
DisplayAlert(AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage,
AppResources.Ok);
}
private void SubscribeFileResult(bool subscribe)
{
MessagingCenter.Unsubscribe<Application, Tuple<byte[], string>>(Application.Current, "SelectFileResult");
if(!subscribe)
{
return;
}
MessagingCenter.Subscribe<Application, Tuple<byte[], string>>(
Application.Current, "SelectFileResult", (sender, result) =>
{
FileLabel.Text = result.Item2;
_fileBytes = result.Item1;
SubscribeFileResult(true);
});
}
2017-07-24 17:34:22 +03:00
private async Task ShowUpdateKeyAsync()
{
var confirmed = await DisplayAlert(AppResources.FeatureUnavailable, AppResources.UpdateKey,
2017-07-24 17:34:22 +03:00
AppResources.LearnMore, AppResources.Cancel);
if(confirmed)
{
2017-07-25 15:51:55 +03:00
Device.OpenUri(new Uri("https://help.bitwarden.com/article/update-encryption-key/"));
2017-07-24 17:34:22 +03:00
}
}
2017-07-22 22:38:08 +03:00
}
}