diff --git a/src/App/App.csproj b/src/App/App.csproj
index 66b694b9e..8db515103 100644
--- a/src/App/App.csproj
+++ b/src/App/App.csproj
@@ -76,12 +76,15 @@
+
+
+
@@ -115,11 +118,11 @@
-
+
-
+
diff --git a/src/App/Models/Page/SettingsFolderPageModel.cs b/src/App/Models/Page/SettingsFolderPageModel.cs
new file mode 100644
index 000000000..646070a9c
--- /dev/null
+++ b/src/App/Models/Page/SettingsFolderPageModel.cs
@@ -0,0 +1,14 @@
+namespace Bit.App.Models.Page
+{
+ public class SettingsFolderPageModel
+ {
+ public SettingsFolderPageModel(Folder folder)
+ {
+ Id = folder.Id;
+ Name = folder.Name?.Decrypt();
+ }
+
+ public string Id { get; set; }
+ public string Name { get; set; }
+ }
+}
diff --git a/src/App/Pages/MainPage.cs b/src/App/Pages/MainPage.cs
index ea1828761..0657c8fd8 100644
--- a/src/App/Pages/MainPage.cs
+++ b/src/App/Pages/MainPage.cs
@@ -13,7 +13,7 @@ namespace Bit.App.Pages
TintColor = Color.FromHex("ffffff");
var settingsNavigation = new ExtendedNavigationPage(new SettingsPage());
- var vaultNavigation = new ExtendedNavigationPage(new VaultListPage());
+ var vaultNavigation = new ExtendedNavigationPage(new VaultListSitesPage());
var syncNavigation = new ExtendedNavigationPage(new SyncPage());
vaultNavigation.Title = AppResources.MyVault;
diff --git a/src/App/Pages/SettingsAddFolderPage.cs b/src/App/Pages/SettingsAddFolderPage.cs
new file mode 100644
index 000000000..ae8dc00e1
--- /dev/null
+++ b/src/App/Pages/SettingsAddFolderPage.cs
@@ -0,0 +1,100 @@
+using System;
+using Acr.UserDialogs;
+using Bit.App.Abstractions;
+using Bit.App.Controls;
+using Bit.App.Models;
+using Bit.App.Resources;
+using Plugin.Connectivity.Abstractions;
+using Xamarin.Forms;
+using XLabs.Ioc;
+
+namespace Bit.App.Pages
+{
+ public class SettingsAddFolderPage : ContentPage
+ {
+ private readonly IFolderService _folderService;
+ private readonly IUserDialogs _userDialogs;
+ private readonly IConnectivity _connectivity;
+
+ public SettingsAddFolderPage()
+ {
+ _folderService = Resolver.Resolve();
+ _userDialogs = Resolver.Resolve();
+ _connectivity = Resolver.Resolve();
+
+ Init();
+ }
+
+ private void Init()
+ {
+ var nameCell = new FormEntryCell(AppResources.Name);
+
+ var mainTable = new ExtendedTableView
+ {
+ Intent = TableIntent.Settings,
+ EnableScrolling = false,
+ HasUnevenRows = true,
+ EnableSelection = false,
+ Root = new TableRoot
+ {
+ new TableSection()
+ {
+ nameCell
+ }
+ }
+ };
+
+ if(Device.OS == TargetPlatform.iOS)
+ {
+ mainTable.RowHeight = -1;
+ mainTable.EstimatedRowHeight = 70;
+ }
+
+ var saveToolBarItem = new ToolbarItem(AppResources.Save, null, async () =>
+ {
+ if(!_connectivity.IsConnected)
+ {
+ AlertNoConnection();
+ return;
+ }
+
+ if(string.IsNullOrWhiteSpace(nameCell.Entry.Text))
+ {
+ await DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.Name), AppResources.Ok);
+ return;
+ }
+
+ var folder = new Folder
+ {
+ Name = nameCell.Entry.Text.Encrypt()
+ };
+
+ var saveTask = _folderService.SaveAsync(folder);
+ _userDialogs.ShowLoading("Saving...", MaskType.Black);
+ await saveTask;
+
+ _userDialogs.HideLoading();
+ await Navigation.PopModalAsync();
+ _userDialogs.SuccessToast(nameCell.Entry.Text, "New folder created.");
+ }, ToolbarItemOrder.Default, 0);
+
+ Title = "Add Folder";
+ Content = mainTable;
+ ToolbarItems.Add(saveToolBarItem);
+ if(Device.OS == TargetPlatform.iOS)
+ {
+ ToolbarItems.Add(new DismissModalToolBarItem(this, "Cancel"));
+ }
+
+ if(!_connectivity.IsConnected)
+ {
+ AlertNoConnection();
+ }
+ }
+
+ private void AlertNoConnection()
+ {
+ DisplayAlert(AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage, AppResources.Ok);
+ }
+ }
+}
diff --git a/src/App/Pages/SettingsEditFolderPage.cs b/src/App/Pages/SettingsEditFolderPage.cs
new file mode 100644
index 000000000..dda8d9030
--- /dev/null
+++ b/src/App/Pages/SettingsEditFolderPage.cs
@@ -0,0 +1,106 @@
+using System;
+using Acr.UserDialogs;
+using Bit.App.Abstractions;
+using Bit.App.Controls;
+using Bit.App.Resources;
+using Plugin.Connectivity.Abstractions;
+using Xamarin.Forms;
+using XLabs.Ioc;
+
+namespace Bit.App.Pages
+{
+ public class SettingsEditFolderPage : ContentPage
+ {
+ private readonly string _folderId;
+ private readonly IFolderService _folderService;
+ private readonly IUserDialogs _userDialogs;
+ private readonly IConnectivity _connectivity;
+
+ public SettingsEditFolderPage(string folderId)
+ {
+ _folderId = folderId;
+ _folderService = Resolver.Resolve();
+ _userDialogs = Resolver.Resolve();
+ _connectivity = Resolver.Resolve();
+
+ Init();
+ }
+
+ private void Init()
+ {
+ var folder = _folderService.GetByIdAsync(_folderId).GetAwaiter().GetResult();
+ if(folder == null)
+ {
+ // TODO: handle error. navigate back? should never happen...
+ return;
+ }
+
+ var nameCell = new FormEntryCell(AppResources.Name);
+ nameCell.Entry.Text = folder.Name.Decrypt();
+
+ var mainTable = new ExtendedTableView
+ {
+ Intent = TableIntent.Settings,
+ EnableScrolling = false,
+ HasUnevenRows = true,
+ EnableSelection = false,
+ Root = new TableRoot
+ {
+ new TableSection()
+ {
+ nameCell
+ }
+ }
+ };
+
+ if(Device.OS == TargetPlatform.iOS)
+ {
+ mainTable.RowHeight = -1;
+ mainTable.EstimatedRowHeight = 70;
+ }
+
+ var saveToolBarItem = new ToolbarItem(AppResources.Save, null, async () =>
+ {
+ if(!_connectivity.IsConnected)
+ {
+ AlertNoConnection();
+ return;
+ }
+
+ if(string.IsNullOrWhiteSpace(nameCell.Entry.Text))
+ {
+ await DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.Name), AppResources.Ok);
+ return;
+ }
+
+ folder.Name = nameCell.Entry.Text.Encrypt();
+
+ var saveTask = _folderService.SaveAsync(folder);
+ _userDialogs.ShowLoading("Saving...", MaskType.Black);
+ await saveTask;
+
+ _userDialogs.HideLoading();
+ await Navigation.PopModalAsync();
+ _userDialogs.SuccessToast(nameCell.Entry.Text, "Folder updated.");
+ }, ToolbarItemOrder.Default, 0);
+
+ Title = "Edit Folder";
+ Content = mainTable;
+ ToolbarItems.Add(saveToolBarItem);
+ if(Device.OS == TargetPlatform.iOS)
+ {
+ ToolbarItems.Add(new DismissModalToolBarItem(this, "Cancel"));
+ }
+
+ if(!_connectivity.IsConnected)
+ {
+ AlertNoConnection();
+ }
+ }
+
+ private void AlertNoConnection()
+ {
+ DisplayAlert(AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage, AppResources.Ok);
+ }
+ }
+}
diff --git a/src/App/Pages/SettingsListFoldersPage.cs b/src/App/Pages/SettingsListFoldersPage.cs
new file mode 100644
index 000000000..63b5c671e
--- /dev/null
+++ b/src/App/Pages/SettingsListFoldersPage.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Threading.Tasks;
+using Acr.UserDialogs;
+using Bit.App.Abstractions;
+using Bit.App.Controls;
+using Bit.App.Models.Page;
+using Bit.App.Resources;
+using Xamarin.Forms;
+using XLabs.Ioc;
+
+namespace Bit.App.Pages
+{
+ public class SettingsListFoldersPage : ContentPage
+ {
+ private readonly IFolderService _folderService;
+ private readonly IUserDialogs _userDialogs;
+ public SettingsListFoldersPage()
+ {
+ _folderService = Resolver.Resolve();
+ _userDialogs = Resolver.Resolve();
+
+ Init();
+ }
+
+ public ObservableCollection Folders { get; private set; } = new ObservableCollection();
+
+ private void Init()
+ {
+ ToolbarItems.Add(new AddFolderToolBarItem(this));
+
+ var listView = new ListView
+ {
+ ItemsSource = Folders,
+ SeparatorColor = Color.FromHex("d2d6de")
+ };
+ listView.ItemSelected += FolderSelected;
+ listView.ItemTemplate = new DataTemplate(() => new SettingsFolderListViewCell(this));
+
+ Title = "Folders";
+ Content = listView;
+ }
+
+ protected override void OnAppearing()
+ {
+ base.OnAppearing();
+ LoadFoldersAsync().Wait();
+ }
+
+ private async Task LoadFoldersAsync()
+ {
+ Folders.Clear();
+
+ var folders = await _folderService.GetAllAsync();
+ foreach(var folder in folders)
+ {
+ var f = new SettingsFolderPageModel(folder);
+ Folders.Add(f);
+ }
+ }
+
+ private void FolderSelected(object sender, SelectedItemChangedEventArgs e)
+ {
+ var folder = e.SelectedItem as SettingsFolderPageModel;
+ var page = new ExtendedNavigationPage(new SettingsEditFolderPage(folder.Id));
+ Navigation.PushModalAsync(page);
+ }
+
+ private class AddFolderToolBarItem : ToolbarItem
+ {
+ private readonly SettingsListFoldersPage _page;
+
+ public AddFolderToolBarItem(SettingsListFoldersPage page)
+ {
+ _page = page;
+ Text = AppResources.Add;
+ Icon = "ion-plus";
+ Clicked += ClickedItem;
+ }
+
+ private async void ClickedItem(object sender, EventArgs e)
+ {
+ var page = new ExtendedNavigationPage(new SettingsAddFolderPage());
+ await _page.Navigation.PushModalAsync(page);
+ }
+ }
+
+ private class SettingsFolderListViewCell : ExtendedTextCell
+ {
+ public SettingsFolderListViewCell(SettingsListFoldersPage page)
+ {
+ this.SetBinding(TextProperty, s => s.Name);
+ TextColor = Color.FromHex("333333");
+ }
+ }
+ }
+}
diff --git a/src/App/Pages/SettingsPage.cs b/src/App/Pages/SettingsPage.cs
index 1ef4b3a89..24f372163 100644
--- a/src/App/Pages/SettingsPage.cs
+++ b/src/App/Pages/SettingsPage.cs
@@ -4,59 +4,134 @@ using Bit.App.Resources;
using Xamarin.Forms;
using XLabs.Ioc;
using Bit.App.Controls;
+using Acr.UserDialogs;
namespace Bit.App.Pages
{
public class SettingsPage : ContentPage
{
private readonly IAuthService _authService;
+ private readonly IUserDialogs _userDialogs;
public SettingsPage()
{
_authService = Resolver.Resolve();
+ _userDialogs = Resolver.Resolve();
Init();
}
private void Init()
{
- var foldersCell = new ExtendedTextCell { Text = "Folders", ShowDisclousure = true };
+ var touchIdCell = new SwitchCell
+ {
+ Text = "Use Touch ID"
+ };
+ touchIdCell.Tapped += TouchIdCell_Tapped;
+
+ var lockOnExitCell = new SwitchCell
+ {
+ Text = "Lock Immediately On Exit"
+ };
+ lockOnExitCell.Tapped += LockOnExitCell_Tapped;
+
+ var changeMasterPasswordCell = new ExtendedTextCell
+ {
+ Text = "Change Master Password"
+ };
+ changeMasterPasswordCell.Tapped += ChangeMasterPasswordCell_Tapped;
+
+ var foldersCell = new ExtendedTextCell
+ {
+ Text = "Folders",
+ ShowDisclousure = true
+ };
foldersCell.Tapped += FoldersCell_Tapped;
+ var lockCell = new ExtendedTextCell
+ {
+ Text = "Lock"
+ };
+ lockCell.Tapped += LockCell_Tapped;
+
+ var logOutCell = new ExtendedTextCell
+ {
+ Text = "Log Out"
+ };
+ logOutCell.Tapped += LogOutCell_Tapped;
+
var table = new ExtendedTableView
{
- EnableScrolling = false,
+ EnableScrolling = true,
Intent = TableIntent.Menu,
Root = new TableRoot
{
+ new TableSection("Security")
+ {
+ touchIdCell,
+ lockOnExitCell,
+ changeMasterPasswordCell
+ },
new TableSection("Manage Folders")
{
foldersCell
+ },
+ new TableSection("Current Session")
+ {
+ lockCell,
+ logOutCell
}
}
};
- var logoutButton = new Button
+ var scrollView = new ScrollView
{
- Text = AppResources.LogOut,
- Command = new Command(() =>
- {
- _authService.LogOut();
- Application.Current.MainPage = new LoginNavigationPage();
- })
+ Content = table
};
- var stackLayout = new StackLayout { };
- stackLayout.Children.Add(table);
- stackLayout.Children.Add(logoutButton);
-
Title = AppResources.Settings;
- Content = stackLayout;
+ Content = table;
+ }
+
+ private void LockCell_Tapped(object sender, EventArgs e)
+ {
+
+ }
+
+ private async void LogOutCell_Tapped(object sender, EventArgs e)
+ {
+ if(!await _userDialogs.ConfirmAsync("Are you sure you want to log out?", null, AppResources.Yes, AppResources.Cancel))
+ {
+ return;
+ }
+
+ _authService.LogOut();
+ Application.Current.MainPage = new LoginNavigationPage();
+ }
+
+ private void LockOnExitCell_Tapped(object sender, EventArgs e)
+ {
+
+ }
+
+ private async void ChangeMasterPasswordCell_Tapped(object sender, EventArgs e)
+ {
+ if(!await _userDialogs.ConfirmAsync("You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?", null, AppResources.Yes, AppResources.Cancel))
+ {
+ return;
+ }
+
+ Device.OpenUri(new Uri("https://vault.bitwarden.com"));
+ }
+
+ private void TouchIdCell_Tapped(object sender, EventArgs e)
+ {
+
}
private void FoldersCell_Tapped(object sender, EventArgs e)
{
-
+ Navigation.PushAsync(new SettingsListFoldersPage());
}
}
}
diff --git a/src/App/Pages/VaultAddFolderPage.cs b/src/App/Pages/VaultAddFolderPage.cs
deleted file mode 100644
index aeb2f898f..000000000
--- a/src/App/Pages/VaultAddFolderPage.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection.Emit;
-using System.Text;
-using System.Threading.Tasks;
-using Acr.UserDialogs;
-using Bit.App.Abstractions;
-using Bit.App.Models;
-using Bit.App.Resources;
-using Plugin.Connectivity.Abstractions;
-using Xamarin.Forms;
-using XLabs.Ioc;
-
-namespace Bit.App.Pages
-{
- public class VaultAddFolderPage : ContentPage
- {
- public VaultAddFolderPage()
- {
- var cryptoService = Resolver.Resolve();
- var folderService = Resolver.Resolve();
- var userDialogs = Resolver.Resolve();
- var connectivity = Resolver.Resolve();
-
- var nameEntry = new Entry();
-
- var stackLayout = new StackLayout();
- stackLayout.Children.Add(new Label { Text = AppResources.Name });
- stackLayout.Children.Add(nameEntry);
-
- var scrollView = new ScrollView
- {
- Content = stackLayout,
- Orientation = ScrollOrientation.Vertical
- };
-
- var saveToolBarItem = new ToolbarItem(AppResources.Save, null, async () =>
- {
- if(!connectivity.IsConnected)
- {
- AlertNoConnection();
- return;
- }
-
- if(string.IsNullOrWhiteSpace(nameEntry.Text))
- {
- await DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.Name), AppResources.Ok);
- return;
- }
-
- var folder = new Folder
- {
- Name = nameEntry.Text.Encrypt()
- };
-
- var saveTask = folderService.SaveAsync(folder);
- userDialogs.ShowLoading("Saving...", MaskType.Black);
- await saveTask;
-
- userDialogs.HideLoading();
- await Navigation.PopAsync();
- userDialogs.SuccessToast(nameEntry.Text, "New folder created.");
- }, ToolbarItemOrder.Default, 0);
-
- Title = "Add Folder";
- Content = scrollView;
- ToolbarItems.Add(saveToolBarItem);
-
- if(!connectivity.IsConnected)
- {
- AlertNoConnection();
- }
- }
-
- public void AlertNoConnection()
- {
- DisplayAlert(AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage, AppResources.Ok);
- }
- }
-}
diff --git a/src/App/Pages/VaultAddSitePage.cs b/src/App/Pages/VaultAddSitePage.cs
index a7f08efb2..d79c6527d 100644
--- a/src/App/Pages/VaultAddSitePage.cs
+++ b/src/App/Pages/VaultAddSitePage.cs
@@ -120,7 +120,7 @@ namespace Bit.App.Pages
await saveTask;
_userDialogs.HideLoading();
- await Navigation.PopAsync();
+ await Navigation.PopModalAsync();
_userDialogs.SuccessToast(nameCell.Entry.Text, "New site created.");
}, ToolbarItemOrder.Default, 0);
@@ -142,15 +142,6 @@ namespace Bit.App.Pages
{
DisplayAlert(AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage, AppResources.Ok);
}
-
- private class FormEntryStackLayout : StackLayout
- {
- public FormEntryStackLayout()
- {
- Padding = new Thickness(15, 15, 15, 0);
- BackgroundColor = Color.White;
- }
- }
}
}
diff --git a/src/App/Pages/VaultListPage.cs b/src/App/Pages/VaultListSitesPage.cs
similarity index 96%
rename from src/App/Pages/VaultListPage.cs
rename to src/App/Pages/VaultListSitesPage.cs
index f5873e0cb..3f37e4d9b 100644
--- a/src/App/Pages/VaultListPage.cs
+++ b/src/App/Pages/VaultListSitesPage.cs
@@ -12,14 +12,14 @@ using XLabs.Ioc;
namespace Bit.App.Pages
{
- public class VaultListPage : ContentPage
+ public class VaultListSitesPage : ContentPage
{
private readonly IFolderService _folderService;
private readonly ISiteService _siteService;
private readonly IUserDialogs _userDialogs;
private readonly IClipboardService _clipboardService;
- public VaultListPage()
+ public VaultListSitesPage()
{
_folderService = Resolver.Resolve();
_siteService = Resolver.Resolve();
@@ -145,9 +145,9 @@ namespace Bit.App.Pages
private class AddSiteToolBarItem : ToolbarItem
{
- private readonly VaultListPage _page;
+ private readonly VaultListSitesPage _page;
- public AddSiteToolBarItem(VaultListPage page)
+ public AddSiteToolBarItem(VaultListSitesPage page)
{
_page = page;
Text = AppResources.Add;
@@ -164,7 +164,7 @@ namespace Bit.App.Pages
private class VaultListViewCell : ExtendedTextCell
{
- public VaultListViewCell(VaultListPage page)
+ public VaultListViewCell(VaultListSitesPage page)
{
var moreAction = new MenuItem { Text = AppResources.More };
moreAction.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));
@@ -181,13 +181,12 @@ namespace Bit.App.Pages
TextColor = Color.FromHex("333333");
DetailColor = Color.FromHex("777777");
- BackgroundColor = Color.White;
}
}
private class VaultListHeaderViewCell : ViewCell
{
- public VaultListHeaderViewCell(VaultListPage page)
+ public VaultListHeaderViewCell(VaultListSitesPage page)
{
var image = new Image
{