2016-05-02 09:52:09 +03:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.ObjectModel;
|
|
|
|
|
using System.Linq;
|
2016-05-04 02:49:49 +03:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Acr.UserDialogs;
|
2016-05-02 09:52:09 +03:00
|
|
|
|
using Bit.App.Abstractions;
|
2016-05-13 07:11:32 +03:00
|
|
|
|
using Bit.App.Controls;
|
2016-05-08 06:11:47 +03:00
|
|
|
|
using Bit.App.Models.Page;
|
2016-05-07 10:06:27 +03:00
|
|
|
|
using Bit.App.Resources;
|
2016-05-02 09:52:09 +03:00
|
|
|
|
using Xamarin.Forms;
|
|
|
|
|
using XLabs.Ioc;
|
2016-05-19 03:29:03 +03:00
|
|
|
|
using Bit.App.Utilities;
|
2016-06-15 07:36:50 +03:00
|
|
|
|
using System.Diagnostics;
|
2016-05-02 09:52:09 +03:00
|
|
|
|
|
2016-05-03 00:50:16 +03:00
|
|
|
|
namespace Bit.App.Pages
|
2016-05-02 09:52:09 +03:00
|
|
|
|
{
|
2016-05-18 06:09:20 +03:00
|
|
|
|
public class VaultListSitesPage : ContentPage
|
2016-05-02 09:52:09 +03:00
|
|
|
|
{
|
|
|
|
|
private readonly IFolderService _folderService;
|
|
|
|
|
private readonly ISiteService _siteService;
|
2016-05-04 02:49:49 +03:00
|
|
|
|
private readonly IUserDialogs _userDialogs;
|
2016-05-07 20:42:09 +03:00
|
|
|
|
private readonly IClipboardService _clipboardService;
|
2016-06-15 06:23:05 +03:00
|
|
|
|
private readonly bool _favorites;
|
2016-05-02 09:52:09 +03:00
|
|
|
|
|
2016-06-15 06:23:05 +03:00
|
|
|
|
public VaultListSitesPage(bool favorites)
|
2016-05-02 09:52:09 +03:00
|
|
|
|
{
|
2016-06-15 06:23:05 +03:00
|
|
|
|
_favorites = favorites;
|
2016-05-02 09:52:09 +03:00
|
|
|
|
_folderService = Resolver.Resolve<IFolderService>();
|
|
|
|
|
_siteService = Resolver.Resolve<ISiteService>();
|
2016-05-04 02:49:49 +03:00
|
|
|
|
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
2016-05-07 20:42:09 +03:00
|
|
|
|
_clipboardService = Resolver.Resolve<IClipboardService>();
|
2016-05-02 09:52:09 +03:00
|
|
|
|
|
2016-05-04 02:49:49 +03:00
|
|
|
|
Init();
|
|
|
|
|
}
|
2016-05-03 01:35:01 +03:00
|
|
|
|
|
2016-05-19 03:29:03 +03:00
|
|
|
|
public ExtendedObservableCollection<VaultListPageModel.Folder> Folders { get; private set; } = new ExtendedObservableCollection<VaultListPageModel.Folder>();
|
2016-05-02 09:52:09 +03:00
|
|
|
|
|
2016-05-04 02:49:49 +03:00
|
|
|
|
private void Init()
|
|
|
|
|
{
|
2016-06-15 06:23:05 +03:00
|
|
|
|
if(!_favorites)
|
|
|
|
|
{
|
|
|
|
|
ToolbarItems.Add(new AddSiteToolBarItem(this));
|
|
|
|
|
}
|
2016-05-02 09:52:09 +03:00
|
|
|
|
|
2016-05-14 08:34:42 +03:00
|
|
|
|
var listView = new ListView
|
|
|
|
|
{
|
2016-06-16 06:39:49 +03:00
|
|
|
|
Margin = new Thickness(0, 0, -15, 0),
|
2016-05-14 08:34:42 +03:00
|
|
|
|
IsGroupingEnabled = true,
|
|
|
|
|
ItemsSource = Folders,
|
|
|
|
|
HasUnevenRows = true,
|
2016-05-19 06:30:46 +03:00
|
|
|
|
SeparatorColor = Color.FromHex("d2d6de"),
|
|
|
|
|
GroupHeaderTemplate = new DataTemplate(() => new VaultListHeaderViewCell(this)),
|
|
|
|
|
ItemTemplate = new DataTemplate(() => new VaultListViewCell(this))
|
2016-05-14 08:34:42 +03:00
|
|
|
|
};
|
2016-05-04 02:49:49 +03:00
|
|
|
|
listView.ItemSelected += SiteSelected;
|
2016-05-02 09:52:09 +03:00
|
|
|
|
|
2016-06-15 06:23:05 +03:00
|
|
|
|
Title = _favorites ? AppResources.Favorites : AppResources.MyVault;
|
2016-05-04 02:49:49 +03:00
|
|
|
|
Content = listView;
|
2016-05-02 09:52:09 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void OnAppearing()
|
|
|
|
|
{
|
|
|
|
|
base.OnAppearing();
|
2016-05-04 02:49:49 +03:00
|
|
|
|
LoadFoldersAsync().Wait();
|
|
|
|
|
}
|
2016-05-02 09:52:09 +03:00
|
|
|
|
|
2016-05-04 02:49:49 +03:00
|
|
|
|
private async Task LoadFoldersAsync()
|
|
|
|
|
{
|
|
|
|
|
var folders = await _folderService.GetAllAsync();
|
2016-06-15 06:23:05 +03:00
|
|
|
|
var sites = _favorites ? await _siteService.GetAllAsync(true) : await _siteService.GetAllAsync();
|
2016-05-04 02:49:49 +03:00
|
|
|
|
|
2016-05-19 03:29:03 +03:00
|
|
|
|
var pageFolders = folders.Select(f => new VaultListPageModel.Folder(f, sites.Where(s => s.FolderId == f.Id))).ToList();
|
2016-05-08 06:11:47 +03:00
|
|
|
|
var noneFolder = new VaultListPageModel.Folder(sites.Where(s => s.FolderId == null));
|
2016-05-19 03:29:03 +03:00
|
|
|
|
pageFolders.Add(noneFolder);
|
|
|
|
|
|
2016-06-15 05:19:40 +03:00
|
|
|
|
Folders.ResetWithRange(pageFolders.Where(f => f.Any()));
|
2016-05-02 09:52:09 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-05-04 02:49:49 +03:00
|
|
|
|
private void SiteSelected(object sender, SelectedItemChangedEventArgs e)
|
2016-05-02 09:52:09 +03:00
|
|
|
|
{
|
2016-05-08 06:11:47 +03:00
|
|
|
|
var site = e.SelectedItem as VaultListPageModel.Site;
|
2016-05-13 07:11:32 +03:00
|
|
|
|
var page = new ExtendedNavigationPage(new VaultViewSitePage(site.Id));
|
|
|
|
|
Navigation.PushModalAsync(page);
|
2016-05-02 09:52:09 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-05-04 02:49:49 +03:00
|
|
|
|
private async void MoreClickedAsync(object sender, EventArgs e)
|
2016-05-02 09:52:09 +03:00
|
|
|
|
{
|
2016-06-15 07:36:50 +03:00
|
|
|
|
var cell = sender as VaultListViewCell;
|
|
|
|
|
var site = cell.CommandParameter as VaultListPageModel.Site;
|
2016-05-07 20:42:09 +03:00
|
|
|
|
var selection = await DisplayActionSheet(AppResources.MoreOptions, AppResources.Cancel, null,
|
|
|
|
|
AppResources.View, AppResources.Edit, AppResources.CopyPassword, AppResources.CopyUsername, AppResources.GoToWebsite);
|
2016-05-02 09:52:09 +03:00
|
|
|
|
|
2016-05-07 20:42:09 +03:00
|
|
|
|
if(selection == AppResources.View)
|
2016-05-04 02:49:49 +03:00
|
|
|
|
{
|
2016-05-13 07:11:32 +03:00
|
|
|
|
var page = new ExtendedNavigationPage(new VaultViewSitePage(site.Id));
|
|
|
|
|
await Navigation.PushModalAsync(page);
|
2016-05-04 02:49:49 +03:00
|
|
|
|
}
|
2016-05-07 20:42:09 +03:00
|
|
|
|
else if(selection == AppResources.Edit)
|
|
|
|
|
{
|
2016-05-13 07:11:32 +03:00
|
|
|
|
var page = new ExtendedNavigationPage(new VaultEditSitePage(site.Id));
|
|
|
|
|
await Navigation.PushModalAsync(page);
|
2016-05-07 20:42:09 +03:00
|
|
|
|
}
|
|
|
|
|
else if(selection == AppResources.CopyPassword)
|
|
|
|
|
{
|
|
|
|
|
Copy(site.Password, AppResources.Password);
|
|
|
|
|
}
|
|
|
|
|
else if(selection == AppResources.CopyUsername)
|
|
|
|
|
{
|
|
|
|
|
Copy(site.Username, AppResources.Username);
|
|
|
|
|
}
|
|
|
|
|
else if(selection == AppResources.GoToWebsite)
|
|
|
|
|
{
|
|
|
|
|
Device.OpenUri(new Uri(site.Uri));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Copy(string copyText, string alertLabel)
|
|
|
|
|
{
|
|
|
|
|
_clipboardService.CopyToClipboard(copyText);
|
|
|
|
|
_userDialogs.SuccessToast(string.Format(AppResources.ValueHasBeenCopied, alertLabel));
|
2016-05-04 02:49:49 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async void DeleteClickedAsync(object sender, EventArgs e)
|
|
|
|
|
{
|
2016-05-07 20:42:09 +03:00
|
|
|
|
if(!await _userDialogs.ConfirmAsync(AppResources.DoYouReallyWantToDelete, null, AppResources.Yes, AppResources.No))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-04 02:49:49 +03:00
|
|
|
|
var mi = sender as MenuItem;
|
2016-05-08 06:11:47 +03:00
|
|
|
|
var site = mi.CommandParameter as VaultListPageModel.Site;
|
2016-05-04 02:49:49 +03:00
|
|
|
|
var deleteCall = await _siteService.DeleteAsync(site.Id);
|
|
|
|
|
|
|
|
|
|
if(deleteCall.Succeeded)
|
|
|
|
|
{
|
|
|
|
|
var folder = Folders.Single(f => f.Id == site.FolderId);
|
|
|
|
|
var siteIndex = folder.Select((s, i) => new { s, i }).First(s => s.s.Id == site.Id).i;
|
|
|
|
|
folder.RemoveAt(siteIndex);
|
2016-05-07 20:42:09 +03:00
|
|
|
|
_userDialogs.SuccessToast(AppResources.SiteDeleted);
|
2016-05-04 02:49:49 +03:00
|
|
|
|
}
|
|
|
|
|
else if(deleteCall.Errors.Count() > 0)
|
|
|
|
|
{
|
2016-05-07 20:42:09 +03:00
|
|
|
|
await DisplayAlert(AppResources.AnErrorHasOccurred, deleteCall.Errors.First().Message, AppResources.Ok);
|
2016-05-04 02:49:49 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class AddSiteToolBarItem : ToolbarItem
|
|
|
|
|
{
|
2016-05-18 06:09:20 +03:00
|
|
|
|
private readonly VaultListSitesPage _page;
|
2016-05-04 02:49:49 +03:00
|
|
|
|
|
2016-05-18 06:09:20 +03:00
|
|
|
|
public AddSiteToolBarItem(VaultListSitesPage page)
|
2016-05-04 02:49:49 +03:00
|
|
|
|
{
|
|
|
|
|
_page = page;
|
2016-05-07 20:42:09 +03:00
|
|
|
|
Text = AppResources.Add;
|
2016-06-14 05:09:16 +03:00
|
|
|
|
Icon = "plus";
|
2016-05-04 02:49:49 +03:00
|
|
|
|
Clicked += ClickedItem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async void ClickedItem(object sender, EventArgs e)
|
|
|
|
|
{
|
2016-05-13 07:11:32 +03:00
|
|
|
|
var page = new ExtendedNavigationPage(new VaultAddSitePage());
|
|
|
|
|
await _page.Navigation.PushModalAsync(page);
|
2016-05-04 02:49:49 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-17 05:47:36 +03:00
|
|
|
|
private class VaultListViewCell : ExtendedTextCell
|
2016-05-04 02:49:49 +03:00
|
|
|
|
{
|
2016-06-15 07:36:50 +03:00
|
|
|
|
private VaultListSitesPage _page;
|
|
|
|
|
|
2016-05-18 06:09:20 +03:00
|
|
|
|
public VaultListViewCell(VaultListSitesPage page)
|
2016-05-04 02:49:49 +03:00
|
|
|
|
{
|
2016-06-15 07:36:50 +03:00
|
|
|
|
_page = page;
|
2016-05-06 07:17:38 +03:00
|
|
|
|
|
2016-05-07 20:42:09 +03:00
|
|
|
|
var deleteAction = new MenuItem { Text = AppResources.Delete, IsDestructive = true };
|
2016-05-06 07:17:38 +03:00
|
|
|
|
deleteAction.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));
|
|
|
|
|
deleteAction.Clicked += page.DeleteClickedAsync;
|
|
|
|
|
|
2016-06-15 07:36:50 +03:00
|
|
|
|
SetBinding(CommandParameterProperty, new Binding("."));
|
2016-05-08 06:11:47 +03:00
|
|
|
|
this.SetBinding<VaultListPageModel.Site>(TextProperty, s => s.Name);
|
|
|
|
|
this.SetBinding<VaultListPageModel.Site>(DetailProperty, s => s.Username);
|
2016-05-06 07:17:38 +03:00
|
|
|
|
ContextActions.Add(deleteAction);
|
2016-05-14 08:34:42 +03:00
|
|
|
|
|
|
|
|
|
TextColor = Color.FromHex("333333");
|
|
|
|
|
DetailColor = Color.FromHex("777777");
|
2016-06-15 07:36:50 +03:00
|
|
|
|
|
|
|
|
|
DisclousureTapped += VaultListViewCell_DisclousureTapped;
|
|
|
|
|
ShowDisclousure = true;
|
|
|
|
|
DisclousureImage = "more";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void VaultListViewCell_DisclousureTapped(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
_page.MoreClickedAsync(sender, e);
|
2016-05-14 08:34:42 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class VaultListHeaderViewCell : ViewCell
|
|
|
|
|
{
|
2016-05-18 06:09:20 +03:00
|
|
|
|
public VaultListHeaderViewCell(VaultListSitesPage page)
|
2016-05-14 08:34:42 +03:00
|
|
|
|
{
|
|
|
|
|
var image = new Image
|
|
|
|
|
{
|
2016-05-17 05:47:36 +03:00
|
|
|
|
Source = "fa_folder_open.png",
|
|
|
|
|
Margin = new Thickness(16, 0, 0, 0),
|
|
|
|
|
VerticalOptions = LayoutOptions.CenterAndExpand
|
2016-05-14 08:34:42 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var label = new Label
|
|
|
|
|
{
|
|
|
|
|
TextColor = Color.FromHex("777777"),
|
2016-05-17 05:47:36 +03:00
|
|
|
|
VerticalTextAlignment = TextAlignment.Center,
|
2016-05-25 03:14:37 +03:00
|
|
|
|
VerticalOptions = LayoutOptions.CenterAndExpand,
|
|
|
|
|
FontSize = 14
|
2016-05-14 08:34:42 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
label.SetBinding<VaultListPageModel.Folder>(Label.TextProperty, s => s.Name);
|
|
|
|
|
|
|
|
|
|
var stackLayout = new StackLayout
|
|
|
|
|
{
|
|
|
|
|
Orientation = StackOrientation.Horizontal,
|
2016-05-25 03:14:37 +03:00
|
|
|
|
VerticalOptions = LayoutOptions.FillAndExpand,
|
|
|
|
|
Children = { image, label },
|
|
|
|
|
BackgroundColor = Color.FromHex("ecf0f5")
|
2016-05-14 08:34:42 +03:00
|
|
|
|
};
|
2016-06-15 05:19:40 +03:00
|
|
|
|
|
2016-05-25 03:14:37 +03:00
|
|
|
|
View = stackLayout;
|
|
|
|
|
Height = 30;
|
2016-05-04 02:49:49 +03:00
|
|
|
|
}
|
2016-05-02 09:52:09 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|