1
0
mirror of https://github.com/bitwarden/mobile synced 2026-01-08 03:23:23 +00:00

reset for v2

This commit is contained in:
Kyle Spearrin
2019-03-27 16:23:00 -04:00
parent 5a7f106e3e
commit 297beac169
1180 changed files with 0 additions and 126197 deletions

View File

@@ -1,110 +0,0 @@
using System;
using Bit.App.Controls;
using Xamarin.Forms;
using Bit.App.Abstractions;
using XLabs.Ioc;
using Bit.App.Resources;
using FFImageLoading.Forms;
using Bit.App.Utilities;
namespace Bit.App.Pages
{
public class SettingsAboutPage : ExtendedContentPage
{
private readonly IAppInfoService _appInfoService;
public SettingsAboutPage()
{
_appInfoService = Resolver.Resolve<IAppInfoService>();
Init();
}
public ExtendedTextCell CreditsCell { get; set; }
public void Init()
{
var logo = new CachedImage
{
Source = "logo.png",
HorizontalOptions = LayoutOptions.Center,
WidthRequest = 282,
HeightRequest = 44
};
var versionLabel = new Label
{
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
Text = $@"{AppResources.Version} {_appInfoService.Version} ({_appInfoService.Build})
© 8bit Solutions LLC 2015-{DateTime.Now.Year}",
HorizontalTextAlignment = TextAlignment.Center
};
var logoVersionStackLayout = new StackLayout
{
Children = { logo, versionLabel },
Spacing = 20,
Padding = new Thickness(0, 40, 0, 0)
};
CreditsCell = new ExtendedTextCell
{
Text = AppResources.Credits,
ShowDisclousure = true
};
var table = new ExtendedTableView
{
VerticalOptions = LayoutOptions.Start,
EnableScrolling = false,
Intent = TableIntent.Settings,
HasUnevenRows = true,
Root = new TableRoot
{
new TableSection(Helpers.GetEmptyTableSectionTitle())
{
CreditsCell
}
}
};
if(Device.RuntimePlatform == Device.iOS)
{
table.RowHeight = -1;
table.EstimatedRowHeight = 44;
}
var stackLayout = new RedrawableStackLayout
{
Children = { logoVersionStackLayout, table },
Spacing = 0
};
table.WrappingStackLayout = () => stackLayout;
if(Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.UWP)
{
ToolbarItems.Add(new DismissModalToolBarItem(this, AppResources.Close));
}
Title = AppResources.About;
Content = new ScrollView { Content = stackLayout };
}
private void RateCell_Tapped(object sender, EventArgs e)
{
Navigation.PushAsync(new SettingsCreditsPage());
}
protected override void OnAppearing()
{
base.OnAppearing();
CreditsCell.Tapped += RateCell_Tapped;
}
protected override void OnDisappearing()
{
base.OnDisappearing();
CreditsCell.Tapped -= RateCell_Tapped;
}
}
}

View File

@@ -1,134 +0,0 @@
using System;
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;
using System.Linq;
using Bit.App.Utilities;
namespace Bit.App.Pages
{
public class SettingsAddFolderPage : ExtendedContentPage
{
private readonly IFolderService _folderService;
private readonly IDeviceActionService _deviceActionService;
private readonly IConnectivity _connectivity;
private readonly IGoogleAnalyticsService _googleAnalyticsService;
private DateTime? _lastAction;
public SettingsAddFolderPage()
{
_folderService = Resolver.Resolve<IFolderService>();
_deviceActionService = Resolver.Resolve<IDeviceActionService>();
_connectivity = Resolver.Resolve<IConnectivity>();
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
Init();
}
public FormEntryCell NameCell { get; set; }
private void Init()
{
NameCell = new FormEntryCell(AppResources.Name);
var table = new ExtendedTableView
{
Intent = TableIntent.Settings,
EnableScrolling = false,
HasUnevenRows = true,
Root = new TableRoot
{
new TableSection(Helpers.GetEmptyTableSectionTitle())
{
NameCell
}
}
};
if(Device.RuntimePlatform == Device.iOS)
{
table.RowHeight = -1;
table.EstimatedRowHeight = 70;
}
else if(Device.RuntimePlatform == Device.Android)
{
table.BottomPadding = 50;
}
var saveToolBarItem = new ToolbarItem(AppResources.Save, Helpers.ToolbarImage("envelope.png"), async () =>
{
if(_lastAction.LastActionWasRecent())
{
return;
}
_lastAction = DateTime.UtcNow;
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()
};
await _deviceActionService.ShowLoadingAsync(AppResources.Saving);
var saveResult = await _folderService.SaveAsync(folder);
await _deviceActionService.HideLoadingAsync();
if(saveResult.Succeeded)
{
_deviceActionService.Toast(AppResources.FolderCreated);
_googleAnalyticsService.TrackAppEvent("CreatedFolder");
await Navigation.PopForDeviceAsync();
}
else if(saveResult.Errors.Count() > 0)
{
await DisplayAlert(AppResources.AnErrorHasOccurred, saveResult.Errors.First().Message, AppResources.Ok);
}
else
{
await DisplayAlert(null, AppResources.AnErrorHasOccurred, AppResources.Ok);
}
}, ToolbarItemOrder.Default, 0);
Title = AppResources.AddFolder;
Content = table;
ToolbarItems.Add(saveToolBarItem);
if(Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.UWP)
{
ToolbarItems.Add(new DismissModalToolBarItem(this, AppResources.Cancel));
}
}
protected override void OnAppearing()
{
base.OnAppearing();
NameCell.InitEvents();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
NameCell.Dispose();
}
private void AlertNoConnection()
{
DisplayAlert(AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage, AppResources.Ok);
}
}
}

View File

@@ -1,85 +0,0 @@
using System;
using Bit.App.Controls;
using Xamarin.Forms;
using Bit.App.Resources;
using Bit.App.Utilities;
namespace Bit.App.Pages
{
public class SettingsCreditsPage : ExtendedContentPage
{
public SettingsCreditsPage()
{
Init();
}
public void Init()
{
var table = new ExtendedTableView
{
EnableScrolling = true,
Intent = TableIntent.Settings,
HasUnevenRows = true,
EnableSelection = false,
Root = new TableRoot
{
new TableSection(AppResources.Translations)
{
new CustomViewCell(@"@felixqu - Chinese Simplified
@thomassth - Chinese Traditional
@Primokorn, @maxlandry - French
@bestHippos - Italian
@SW1FT - Portuguese
@majod - Slovak
@King-Tut-Tut - Swedish
@Igetin - Finnish")
},
new TableSection(AppResources.Icons)
{
new CustomViewCell(@"Tools by Alex Auda Samora from the Noun Project
Fingerprint by masterpage.com from the Noun Project")
}
}
};
if(Device.RuntimePlatform == Device.iOS)
{
table.RowHeight = -1;
table.EstimatedRowHeight = 100;
}
Title = AppResources.ThankYou;
Content = table;
}
public class CustomViewCell : ViewCell
{
public CustomViewCell(string text)
{
var label = new Label
{
LineBreakMode = LineBreakMode.WordWrap,
Text = text,
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label))
};
var layout = new StackLayout
{
Children = { label },
Padding = Helpers.OnPlatform(
iOS: new Thickness(15, 20),
Android: new Thickness(16, 20),
Windows: new Thickness(10, 8)),
BackgroundColor = Color.White
};
if(Device.RuntimePlatform == Device.Android)
{
label.TextColor = Color.Black;
}
View = layout;
}
}
}
}

View File

@@ -1,184 +0,0 @@
using System;
using Bit.App.Abstractions;
using Bit.App.Controls;
using Bit.App.Resources;
using Plugin.Connectivity.Abstractions;
using Xamarin.Forms;
using XLabs.Ioc;
using System.Linq;
using Bit.App.Utilities;
namespace Bit.App.Pages
{
public class SettingsEditFolderPage : ExtendedContentPage
{
private readonly string _folderId;
private readonly IFolderService _folderService;
private readonly IDeviceActionService _deviceActionService;
private readonly IConnectivity _connectivity;
private readonly IGoogleAnalyticsService _googleAnalyticsService;
private DateTime? _lastAction;
public SettingsEditFolderPage(string folderId)
{
_folderId = folderId;
_folderService = Resolver.Resolve<IFolderService>();
_deviceActionService = Resolver.Resolve<IDeviceActionService>();
_connectivity = Resolver.Resolve<IConnectivity>();
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
Init();
}
public FormEntryCell NameCell { get; set; }
public ExtendedTextCell DeleteCell { get; set; }
private void Init()
{
var folder = _folderService.GetByIdAsync(_folderId).GetAwaiter().GetResult();
if(folder == null)
{
// TODO: handle error. navigate back? should never happen...
return;
}
NameCell = new FormEntryCell(AppResources.Name);
NameCell.Entry.Text = folder.Name.Decrypt();
DeleteCell = new ExtendedTextCell { Text = AppResources.Delete, TextColor = Color.Red };
var mainTable = new ExtendedTableView
{
Intent = TableIntent.Settings,
HasUnevenRows = true,
Root = new TableRoot
{
new TableSection(Helpers.GetEmptyTableSectionTitle())
{
NameCell
},
new TableSection(Helpers.GetEmptyTableSectionTitle())
{
DeleteCell
}
}
};
if(Device.RuntimePlatform == Device.iOS)
{
mainTable.RowHeight = -1;
mainTable.EstimatedRowHeight = 70;
}
else if(Device.RuntimePlatform == Device.Android)
{
mainTable.BottomPadding = 50;
}
var saveToolBarItem = new ToolbarItem(AppResources.Save, Helpers.ToolbarImage("envelope.png"), async () =>
{
if(_lastAction.LastActionWasRecent())
{
return;
}
_lastAction = DateTime.UtcNow;
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();
await _deviceActionService.ShowLoadingAsync(AppResources.Saving);
var saveResult = await _folderService.SaveAsync(folder);
await _deviceActionService.HideLoadingAsync();
if(saveResult.Succeeded)
{
_deviceActionService.Toast(AppResources.FolderUpdated);
_googleAnalyticsService.TrackAppEvent("EditedFolder");
await Navigation.PopForDeviceAsync();
}
else if(saveResult.Errors.Count() > 0)
{
await DisplayAlert(AppResources.AnErrorHasOccurred, saveResult.Errors.First().Message, AppResources.Ok);
}
else
{
await DisplayAlert(null, AppResources.AnErrorHasOccurred, AppResources.Ok);
}
}, ToolbarItemOrder.Default, 0);
Title = AppResources.EditFolder;
Content = mainTable;
ToolbarItems.Add(saveToolBarItem);
if(Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.UWP)
{
ToolbarItems.Add(new DismissModalToolBarItem(this, AppResources.Cancel));
}
}
protected override void OnAppearing()
{
base.OnAppearing();
NameCell.InitEvents();
DeleteCell.Tapped += DeleteCell_Tapped;
}
protected override void OnDisappearing()
{
base.OnDisappearing();
NameCell.Dispose();
DeleteCell.Tapped -= DeleteCell_Tapped;
}
private async void DeleteCell_Tapped(object sender, EventArgs e)
{
if(!_connectivity.IsConnected)
{
AlertNoConnection();
return;
}
// TODO: Validate the delete operation. ex. Cannot delete a folder that has ciphers in it?
var confirmed = await DisplayAlert(null, AppResources.DoYouReallyWantToDelete, AppResources.Yes, AppResources.No);
if(!confirmed)
{
return;
}
await _deviceActionService.ShowLoadingAsync(AppResources.Deleting);
var deleteTask = await _folderService.DeleteAsync(_folderId);
await _deviceActionService.HideLoadingAsync();
if(deleteTask.Succeeded)
{
_deviceActionService.Toast(AppResources.FolderDeleted);
await Navigation.PopForDeviceAsync();
}
else if(deleteTask.Errors.Count() > 0)
{
await DisplayAlert(AppResources.AnErrorHasOccurred, deleteTask.Errors.First().Message, AppResources.Ok);
}
else
{
await DisplayAlert(null, AppResources.AnErrorHasOccurred, AppResources.Ok);
}
}
private void AlertNoConnection()
{
DisplayAlert(AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage,
AppResources.Ok);
}
}
}

View File

@@ -1,180 +0,0 @@
using System;
using Bit.App.Controls;
using Xamarin.Forms;
using Bit.App.Abstractions;
using XLabs.Ioc;
using Bit.App.Resources;
using Bit.App.Utilities;
namespace Bit.App.Pages
{
public class SettingsHelpPage : ExtendedContentPage
{
private readonly IGoogleAnalyticsService _googleAnalyticsService;
public SettingsHelpPage()
{
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
Init();
}
public ExtendedTextCell EmailCell { get; set; }
public ExtendedTextCell WebsiteCell { get; set; }
public ExtendedTextCell BugCell { get; set; }
public RedrawableStackLayout StackLayout { get; set; }
private CustomLabel EmailLabel { get; set; }
private CustomLabel WebsiteLabel { get; set; }
private CustomLabel BugLabel { get; set; }
public void Init()
{
EmailCell = new ExtendedTextCell
{
Text = AppResources.EmailUs,
ShowDisclousure = true
};
var emailTable = new CustomTableView(this)
{
Root = new TableRoot
{
new TableSection(Helpers.GetEmptyTableSectionTitle())
{
EmailCell
}
}
};
EmailLabel = new CustomLabel(this)
{
Text = AppResources.EmailUsDescription
};
WebsiteCell = new ExtendedTextCell
{
Text = AppResources.VisitOurWebsite,
ShowDisclousure = true
};
var websiteTable = new CustomTableView(this)
{
NoHeader = true,
Root = new TableRoot
{
new TableSection(Helpers.GetEmptyTableSectionTitle())
{
WebsiteCell
}
}
};
WebsiteLabel = new CustomLabel(this)
{
Text = AppResources.VisitOurWebsiteDescription
};
BugCell = new ExtendedTextCell
{
Text = AppResources.FileBugReport,
ShowDisclousure = true
};
var bugTable = new CustomTableView(this)
{
NoHeader = true,
Root = new TableRoot
{
new TableSection(Helpers.GetEmptyTableSectionTitle())
{
BugCell
}
}
};
BugLabel = new CustomLabel(this)
{
Text = AppResources.FileBugReportDescription
};
StackLayout = new RedrawableStackLayout
{
Children = { emailTable, EmailLabel, websiteTable, WebsiteLabel, bugTable, BugLabel },
Spacing = 0
};
if(Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.UWP)
{
ToolbarItems.Add(new DismissModalToolBarItem(this, AppResources.Close));
}
Title = AppResources.HelpAndFeedback;
Content = new ScrollView { Content = StackLayout };
}
protected override void OnAppearing()
{
base.OnAppearing();
EmailCell.Tapped += EmailCell_Tapped;
WebsiteCell.Tapped += WebsiteCell_Tapped;
BugCell.Tapped += BugCell_Tapped;
}
protected override void OnDisappearing()
{
base.OnDisappearing();
EmailCell.Tapped -= EmailCell_Tapped;
WebsiteCell.Tapped -= WebsiteCell_Tapped;
BugCell.Tapped -= BugCell_Tapped;
}
private void EmailCell_Tapped(object sender, EventArgs e)
{
_googleAnalyticsService.TrackAppEvent("HelpEmail");
Device.OpenUri(new Uri("mailto:hello@bitwarden.com"));
}
private void WebsiteCell_Tapped(object sender, EventArgs e)
{
_googleAnalyticsService.TrackAppEvent("HelpWebsite");
Device.OpenUri(new Uri("https://bitwarden.com/contact/"));
}
private void BugCell_Tapped(object sender, EventArgs e)
{
_googleAnalyticsService.TrackAppEvent("HelpBug");
Device.OpenUri(new Uri("https://github.com/bitwarden/mobile"));
}
private class CustomTableView : ExtendedTableView
{
public CustomTableView(SettingsHelpPage page)
{
Intent = TableIntent.Settings;
EnableScrolling = false;
HasUnevenRows = true;
EnableSelection = true;
VerticalOptions = LayoutOptions.Start;
NoFooter = true;
WrappingStackLayout = () => page.StackLayout;
if(Device.RuntimePlatform == Device.iOS)
{
RowHeight = -1;
EstimatedRowHeight = 44;
}
}
}
private class CustomLabel : Label
{
public CustomLabel(ContentPage page)
{
LineBreakMode = LineBreakMode.WordWrap;
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label));
Style = (Style)Application.Current.Resources["text-muted"];
Margin = new Thickness(15, (page.IsLandscape() ? 5 : 0), 15, 25);
}
}
}
}

View File

@@ -1,118 +0,0 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Bit.App.Abstractions;
using Bit.App.Controls;
using Bit.App.Models.Page;
using Bit.App.Resources;
using Bit.App.Utilities;
using Xamarin.Forms;
using XLabs.Ioc;
namespace Bit.App.Pages
{
public class SettingsListFoldersPage : ExtendedContentPage
{
private readonly IFolderService _folderService;
public SettingsListFoldersPage()
{
_folderService = Resolver.Resolve<IFolderService>();
Init();
}
public ExtendedObservableCollection<SettingsFolderPageModel> Folders { get; private set; }
= new ExtendedObservableCollection<SettingsFolderPageModel>();
public ExtendedListView ListView { get; set; }
private AddFolderToolBarItem AddItem { get; set; }
public Fab Fab { get; set; }
private void Init()
{
ListView = new ExtendedListView
{
ItemsSource = Folders,
ItemTemplate = new DataTemplate(() => new SettingsFolderListViewCell(this))
};
if(Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.UWP)
{
ToolbarItems.Add(new DismissModalToolBarItem(this, AppResources.Close));
}
var fabLayout = new FabLayout(ListView);
if(Device.RuntimePlatform == Device.Android)
{
Fab = new Fab(fabLayout, "plus.png", async (sender, args) =>
{
await Navigation.PushForDeviceAsync(new SettingsAddFolderPage());
});
ListView.BottomPadding = 50;
}
else
{
AddItem = new AddFolderToolBarItem(this);
ToolbarItems.Add(AddItem);
}
Title = AppResources.Folders;
Content = fabLayout;
}
protected override void OnAppearing()
{
base.OnAppearing();
ListView.ItemSelected += FolderSelected;
AddItem?.InitEvents();
LoadFoldersAsync().Wait();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
ListView.ItemSelected -= FolderSelected;
AddItem?.Dispose();
}
private async Task LoadFoldersAsync()
{
var folders = await _folderService.GetAllAsync();
var pageFolders = folders.Select(f => new SettingsFolderPageModel(f)).OrderBy(f => f.Name);
Folders.ResetWithRange(pageFolders);
}
private async void FolderSelected(object sender, SelectedItemChangedEventArgs e)
{
var folder = e.SelectedItem as SettingsFolderPageModel;
var page = new SettingsEditFolderPage(folder.Id);
await Navigation.PushForDeviceAsync(page);
}
private class AddFolderToolBarItem : ExtendedToolbarItem
{
private readonly SettingsListFoldersPage _page;
public AddFolderToolBarItem(SettingsListFoldersPage page)
{
_page = page;
Text = AppResources.Add;
Icon = "plus.png";
ClickAction = () => ClickedItem();
}
private async void ClickedItem()
{
var page = new SettingsAddFolderPage();
await _page.Navigation.PushForDeviceAsync(page);
}
}
private class SettingsFolderListViewCell : ExtendedTextCell
{
public SettingsFolderListViewCell(SettingsListFoldersPage page)
{
this.SetBinding(TextProperty, nameof(SettingsFolderPageModel.Name));
}
}
}
}

View File

@@ -1,310 +0,0 @@
using System;
using Bit.App.Abstractions;
using Bit.App.Resources;
using Xamarin.Forms;
using XLabs.Ioc;
using Bit.App.Controls;
using Plugin.Settings.Abstractions;
using Bit.App.Utilities;
namespace Bit.App.Pages
{
public class SettingsOptionsPage : ExtendedContentPage
{
private readonly ISettings _settings;
private readonly IAppSettingsService _appSettings;
public SettingsOptionsPage()
{
_settings = Resolver.Resolve<ISettings>();
_appSettings = Resolver.Resolve<IAppSettingsService>();
Init();
}
private RedrawableStackLayout StackLayout { get; set; }
private ExtendedSwitchCell CopyTotpCell { get; set; }
private Label CopyTotpLabel { get; set; }
private ExtendedSwitchCell WebsiteIconsCell { get; set; }
private Label WebsiteIconsLabel { get; set; }
private ExtendedSwitchCell AutofillPersistNotificationCell { get; set; }
private Label AutofillPersistNotificationLabel { get; set; }
private ExtendedSwitchCell AutofillPasswordFieldCell { get; set; }
private Label AutofillPasswordFieldLabel { get; set; }
private ExtendedSwitchCell AutofillAlwaysCell { get; set; }
private Label AutofillAlwaysLabel { get; set; }
private void Init()
{
WebsiteIconsCell = new ExtendedSwitchCell
{
Text = AppResources.DisableWebsiteIcons,
On = _appSettings.DisableWebsiteIcons
};
var websiteIconsTable = new FormTableView(this, true)
{
Root = new TableRoot
{
new TableSection(Helpers.GetEmptyTableSectionTitle())
{
WebsiteIconsCell
}
}
};
CopyTotpCell = new ExtendedSwitchCell
{
Text = AppResources.DisableAutoTotpCopy,
On = _settings.GetValueOrDefault(Constants.SettingDisableTotpCopy, false)
};
var totpTable = new FormTableView(this)
{
Root = new TableRoot
{
new TableSection(Helpers.GetEmptyTableSectionTitle())
{
CopyTotpCell
}
}
};
CopyTotpLabel = new FormTableLabel(this)
{
Text = AppResources.DisableAutoTotpCopyDescription
};
WebsiteIconsLabel = new FormTableLabel(this)
{
Text = AppResources.DisableWebsiteIconsDescription
};
StackLayout = new RedrawableStackLayout
{
Children =
{
websiteIconsTable, WebsiteIconsLabel,
totpTable, CopyTotpLabel
},
Spacing = 0
};
if(Device.RuntimePlatform == Device.Android)
{
AutofillAlwaysCell = new ExtendedSwitchCell
{
Text = AppResources.AutofillAlways,
On = !_appSettings.AutofillPersistNotification && !_appSettings.AutofillPasswordField
};
var autofillAlwaysTable = new FormTableView(this, true)
{
Root = new TableRoot
{
new TableSection(AppResources.AutofillAccessibilityService)
{
AutofillAlwaysCell
}
}
};
AutofillAlwaysLabel = new FormTableLabel(this)
{
Text = AppResources.AutofillAlwaysDescription
};
AutofillPersistNotificationCell = new ExtendedSwitchCell
{
Text = AppResources.AutofillPersistNotification,
On = _appSettings.AutofillPersistNotification
};
var autofillPersistNotificationTable = new FormTableView(this)
{
Root = new TableRoot
{
new TableSection(Helpers.GetEmptyTableSectionTitle())
{
AutofillPersistNotificationCell
}
}
};
AutofillPersistNotificationLabel = new FormTableLabel(this)
{
Text = AppResources.AutofillPersistNotificationDescription
};
AutofillPasswordFieldCell = new ExtendedSwitchCell
{
Text = AppResources.AutofillPasswordField,
On = _appSettings.AutofillPasswordField
};
var autofillPasswordFieldTable = new FormTableView(this)
{
Root = new TableRoot
{
new TableSection(Helpers.GetEmptyTableSectionTitle())
{
AutofillPasswordFieldCell
}
}
};
AutofillPasswordFieldLabel = new FormTableLabel(this)
{
Text = AppResources.AutofillPasswordFieldDescription
};
StackLayout.Children.Add(autofillAlwaysTable);
StackLayout.Children.Add(AutofillAlwaysLabel);
StackLayout.Children.Add(autofillPasswordFieldTable);
StackLayout.Children.Add(AutofillPasswordFieldLabel);
StackLayout.Children.Add(autofillPersistNotificationTable);
StackLayout.Children.Add(AutofillPersistNotificationLabel);
}
var scrollView = new ScrollView
{
Content = StackLayout
};
if(Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.UWP)
{
ToolbarItems.Add(new DismissModalToolBarItem(this, AppResources.Close));
}
Title = AppResources.Options;
Content = scrollView;
}
protected override void OnAppearing()
{
base.OnAppearing();
WebsiteIconsCell.OnChanged += WebsiteIconsCell_Changed;
CopyTotpCell.OnChanged += CopyTotpCell_OnChanged;
if(Device.RuntimePlatform == Device.Android)
{
AutofillAlwaysCell.OnChanged += AutofillAlwaysCell_OnChanged;
AutofillPasswordFieldCell.OnChanged += AutofillPasswordFieldCell_OnChanged;
AutofillPersistNotificationCell.OnChanged += AutofillPersistNotificationCell_OnChanged;
}
}
protected override void OnDisappearing()
{
base.OnDisappearing();
WebsiteIconsCell.OnChanged -= WebsiteIconsCell_Changed;
CopyTotpCell.OnChanged -= CopyTotpCell_OnChanged;
if(Device.RuntimePlatform == Device.Android)
{
AutofillAlwaysCell.OnChanged -= AutofillAlwaysCell_OnChanged;
AutofillPasswordFieldCell.OnChanged -= AutofillPasswordFieldCell_OnChanged;
AutofillPersistNotificationCell.OnChanged -= AutofillPersistNotificationCell_OnChanged;
}
}
private void WebsiteIconsCell_Changed(object sender, ToggledEventArgs e)
{
var cell = sender as ExtendedSwitchCell;
if(cell == null)
{
return;
}
_appSettings.DisableWebsiteIcons = cell.On;
}
private void CopyTotpCell_OnChanged(object sender, ToggledEventArgs e)
{
var cell = sender as ExtendedSwitchCell;
if(cell == null)
{
return;
}
_settings.AddOrUpdateValue(Constants.SettingDisableTotpCopy, cell.On);
}
private void AutofillAlwaysCell_OnChanged(object sender, ToggledEventArgs e)
{
var cell = sender as ExtendedSwitchCell;
if(cell == null)
{
return;
}
if(cell.On)
{
AutofillPasswordFieldCell.On = false;
AutofillPersistNotificationCell.On = false;
_appSettings.AutofillPersistNotification = false;
_appSettings.AutofillPasswordField = false;
}
}
private void AutofillPersistNotificationCell_OnChanged(object sender, ToggledEventArgs e)
{
var cell = sender as ExtendedSwitchCell;
if(cell == null)
{
return;
}
_appSettings.AutofillPersistNotification = cell.On;
if(cell.On)
{
AutofillPasswordFieldCell.On = false;
AutofillAlwaysCell.On = false;
}
}
private void AutofillPasswordFieldCell_OnChanged(object sender, ToggledEventArgs e)
{
var cell = sender as ExtendedSwitchCell;
if(cell == null)
{
return;
}
_appSettings.AutofillPasswordField = cell.On;
if(cell.On)
{
AutofillPersistNotificationCell.On = false;
AutofillAlwaysCell.On = false;
}
}
private class FormTableView : ExtendedTableView
{
public FormTableView(SettingsOptionsPage page, bool header = false)
{
Intent = TableIntent.Settings;
EnableScrolling = false;
HasUnevenRows = true;
EnableSelection = true;
VerticalOptions = LayoutOptions.Start;
NoFooter = true;
NoHeader = !header;
WrappingStackLayout = () => page.StackLayout;
}
}
private class FormTableLabel : Label
{
public FormTableLabel(Page page)
{
LineBreakMode = LineBreakMode.WordWrap;
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label));
Style = (Style)Application.Current.Resources["text-muted"];
Margin = new Thickness(15, (page.IsLandscape() ? 5 : 0), 15, 25);
}
}
}
}

View File

@@ -1,552 +0,0 @@
using System;
using Bit.App.Abstractions;
using Bit.App.Resources;
using Xamarin.Forms;
using XLabs.Ioc;
using Bit.App.Controls;
using Plugin.Settings.Abstractions;
using Plugin.Fingerprint.Abstractions;
using Bit.App.Utilities;
namespace Bit.App.Pages
{
public class SettingsPage : ExtendedContentPage
{
private readonly IAuthService _authService;
private readonly ISettings _settings;
private readonly IFingerprint _fingerprint;
private readonly IPushNotificationService _pushNotification;
private readonly IGoogleAnalyticsService _googleAnalyticsService;
private readonly IDeviceActionService _deviceActionService;
private readonly IDeviceInfoService _deviceInfoService;
private readonly ILockService _lockService;
private readonly MainPage _mainPage;
// TODO: Model binding context?
public SettingsPage(MainPage mainPage)
{
_mainPage = mainPage;
_authService = Resolver.Resolve<IAuthService>();
_settings = Resolver.Resolve<ISettings>();
_fingerprint = Resolver.Resolve<IFingerprint>();
_pushNotification = Resolver.Resolve<IPushNotificationService>();
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
_deviceActionService = Resolver.Resolve<IDeviceActionService>();
_deviceInfoService = Resolver.Resolve<IDeviceInfoService>();
_lockService = Resolver.Resolve<ILockService>();
Init();
}
private ExtendedSwitchCell PinCell { get; set; }
private ExtendedSwitchCell FingerprintCell { get; set; }
private ExtendedTextCell LockOptionsCell { get; set; }
private ExtendedTextCell TwoStepCell { get; set; }
private ExtendedTextCell ChangeMasterPasswordCell { get; set; }
private ExtendedTextCell ChangeEmailCell { get; set; }
private ExtendedTextCell FoldersCell { get; set; }
private ExtendedTextCell SyncCell { get; set; }
private ExtendedTextCell LockCell { get; set; }
private ExtendedTextCell LogOutCell { get; set; }
private ExtendedTextCell AboutCell { get; set; }
private ExtendedTextCell HelpCell { get; set; }
private ExtendedTextCell RateCell { get; set; }
private ExtendedTextCell OptionsCell { get; set; }
private LongDetailViewCell RateCellLong { get; set; }
private ExtendedTableView Table { get; set; }
private async void Init()
{
PinCell = new ExtendedSwitchCell
{
Text = AppResources.UnlockWithPIN,
On = _settings.GetValueOrDefault(Constants.SettingPinUnlockOn, false)
};
LockOptionsCell = new ExtendedTextCell
{
Text = AppResources.LockOptions,
Detail = GetLockOptionsDetailsText(),
ShowDisclousure = true
};
TwoStepCell = new ExtendedTextCell
{
Text = AppResources.TwoStepLogin,
ShowDisclousure = true
};
LockCell = new ExtendedTextCell
{
Text = AppResources.Lock
};
var securitySecion = new TableSection(AppResources.Security)
{
LockOptionsCell,
PinCell,
LockCell,
TwoStepCell
};
if((await _fingerprint.GetAvailabilityAsync()) == FingerprintAvailability.Available)
{
var fingerprintName = Helpers.OnPlatform(
iOS: _deviceInfoService.HasFaceIdSupport ? AppResources.FaceID : AppResources.TouchID,
Android: AppResources.Fingerprint,
Windows: AppResources.WindowsHello);
FingerprintCell = new ExtendedSwitchCell
{
Text = string.Format(AppResources.UnlockWith, fingerprintName),
On = _settings.GetValueOrDefault(Constants.SettingFingerprintUnlockOn, false),
IsEnabled = true
};
securitySecion.Insert(1, FingerprintCell);
}
ChangeMasterPasswordCell = new ExtendedTextCell
{
Text = AppResources.ChangeMasterPassword,
ShowDisclousure = true
};
ChangeEmailCell = new ExtendedTextCell
{
Text = AppResources.ChangeEmail,
ShowDisclousure = true
};
FoldersCell = new ExtendedTextCell
{
Text = AppResources.Folders,
ShowDisclousure = true
};
SyncCell = new ExtendedTextCell
{
Text = AppResources.Sync,
ShowDisclousure = true
};
LogOutCell = new ExtendedTextCell
{
Text = AppResources.LogOut
};
AboutCell = new ExtendedTextCell
{
Text = AppResources.About,
ShowDisclousure = true
};
HelpCell = new ExtendedTextCell
{
Text = AppResources.HelpAndFeedback,
ShowDisclousure = true
};
OptionsCell = new ExtendedTextCell
{
Text = AppResources.Options,
ShowDisclousure = true
};
var otherSection = new TableSection(AppResources.Other)
{
OptionsCell,
AboutCell,
HelpCell
};
if(Device.RuntimePlatform == Device.iOS)
{
RateCellLong = new LongDetailViewCell(AppResources.RateTheApp, AppResources.RateTheAppDescriptionAppStore);
otherSection.Add(RateCellLong);
}
else
{
RateCell = new ExtendedTextCell
{
Text = AppResources.RateTheApp,
Detail = AppResources.RateTheAppDescription,
ShowDisclousure = true,
DetailLineBreakMode = LineBreakMode.WordWrap
};
otherSection.Add(RateCell);
}
Table = new CustomTable
{
Root = new TableRoot
{
securitySecion,
new TableSection(AppResources.Account)
{
ChangeMasterPasswordCell,
ChangeEmailCell,
LogOutCell
},
new TableSection(AppResources.Manage)
{
FoldersCell,
SyncCell
},
otherSection
}
};
Title = AppResources.Settings;
Content = Table;
}
protected override void OnAppearing()
{
base.OnAppearing();
PinCell.OnChanged += PinCell_Changed;
LockOptionsCell.Tapped += LockOptionsCell_Tapped;
TwoStepCell.Tapped += TwoStepCell_Tapped;
ChangeMasterPasswordCell.Tapped += ChangeMasterPasswordCell_Tapped;
if(FingerprintCell != null)
{
FingerprintCell.OnChanged += FingerprintCell_Changed;
}
ChangeEmailCell.Tapped += ChangeEmailCell_Tapped;
FoldersCell.Tapped += FoldersCell_Tapped;
SyncCell.Tapped += SyncCell_Tapped;
LockCell.Tapped += LockCell_Tapped;
LogOutCell.Tapped += LogOutCell_Tapped;
AboutCell.Tapped += AboutCell_Tapped;
HelpCell.Tapped += HelpCell_Tapped;
OptionsCell.Tapped += OptionsCell_Tapped;
if(RateCellLong != null)
{
RateCellLong.Tapped += RateCell_Tapped;
}
if(RateCell != null)
{
RateCell.Tapped += RateCell_Tapped;
}
}
protected override void OnDisappearing()
{
base.OnDisappearing();
PinCell.OnChanged -= PinCell_Changed;
LockOptionsCell.Tapped -= LockOptionsCell_Tapped;
TwoStepCell.Tapped -= TwoStepCell_Tapped;
ChangeMasterPasswordCell.Tapped -= ChangeMasterPasswordCell_Tapped;
if(FingerprintCell != null)
{
FingerprintCell.OnChanged -= FingerprintCell_Changed;
}
ChangeEmailCell.Tapped -= ChangeEmailCell_Tapped;
FoldersCell.Tapped -= FoldersCell_Tapped;
SyncCell.Tapped -= SyncCell_Tapped;
LockCell.Tapped -= LockCell_Tapped;
LogOutCell.Tapped -= LogOutCell_Tapped;
AboutCell.Tapped -= AboutCell_Tapped;
HelpCell.Tapped -= HelpCell_Tapped;
OptionsCell.Tapped -= OptionsCell_Tapped;
if(RateCellLong != null)
{
RateCellLong.Tapped -= RateCell_Tapped;
}
if(RateCell != null)
{
RateCell.Tapped -= RateCell_Tapped;
}
}
protected override bool OnBackButtonPressed()
{
if(Device.RuntimePlatform == Device.Android && _mainPage != null)
{
_mainPage.ResetToVaultPage();
return true;
}
return base.OnBackButtonPressed();
}
private async void TwoStepCell_Tapped(object sender, EventArgs e)
{
var confirmed = await DisplayAlert(null, AppResources.TwoStepLoginConfirmation, AppResources.Yes,
AppResources.Cancel);
if(!confirmed)
{
return;
}
_googleAnalyticsService.TrackAppEvent("OpenedSetting", "TwoStep");
Device.OpenUri(new Uri("https://help.bitwarden.com/article/setup-two-step-login/"));
}
private async void LockOptionsCell_Tapped(object sender, EventArgs e)
{
var selection = await DisplayActionSheet(AppResources.LockOptions, AppResources.Cancel, null,
AppResources.LockOptionImmediately, AppResources.LockOption1Minute, AppResources.LockOption15Minutes,
AppResources.LockOption1Hour, AppResources.LockOption4Hours, AppResources.Never);
if(selection == null || selection == AppResources.Cancel)
{
return;
}
if(selection == AppResources.LockOptionImmediately)
{
_settings.AddOrUpdateValue(Constants.SettingLockSeconds, 0);
}
else if(selection == AppResources.LockOption1Minute)
{
_settings.AddOrUpdateValue(Constants.SettingLockSeconds, 60);
}
else if(selection == AppResources.LockOption15Minutes)
{
_settings.AddOrUpdateValue(Constants.SettingLockSeconds, 60 * 15);
}
else if(selection == AppResources.LockOption1Hour)
{
_settings.AddOrUpdateValue(Constants.SettingLockSeconds, 60 * 60);
}
else if(selection == AppResources.LockOption4Hours)
{
_settings.AddOrUpdateValue(Constants.SettingLockSeconds, 60 * 60 * 4);
}
else if(selection == AppResources.Never)
{
_settings.AddOrUpdateValue(Constants.SettingLockSeconds, -1);
}
else
{
return;
}
LockOptionsCell.Detail = selection;
}
private void SyncCell_Tapped(object sender, EventArgs e)
{
Navigation.PushModalAsync(new ExtendedNavigationPage(new SettingsSyncPage()));
}
private void AboutCell_Tapped(object sender, EventArgs e)
{
Navigation.PushModalAsync(new ExtendedNavigationPage(new SettingsAboutPage()));
}
private void RateCell_Tapped(object sender, EventArgs e)
{
_googleAnalyticsService.TrackAppEvent("OpenedSetting", "RateApp");
_deviceActionService.RateApp();
}
private void HelpCell_Tapped(object sender, EventArgs e)
{
Navigation.PushModalAsync(new ExtendedNavigationPage(new SettingsHelpPage()));
}
private void LockCell_Tapped(object sender, EventArgs e)
{
_googleAnalyticsService.TrackAppEvent("Locked");
Device.BeginInvokeOnMainThread(async () => await _lockService.CheckLockAsync(true));
}
private async void LogOutCell_Tapped(object sender, EventArgs e)
{
var confirmed = await DisplayAlert(null, AppResources.LogoutConfirmation, AppResources.Yes,
AppResources.Cancel);
if(!confirmed)
{
return;
}
_authService.LogOut();
}
private async void ChangeMasterPasswordCell_Tapped(object sender, EventArgs e)
{
var confirmed = await DisplayAlert(null, AppResources.ChangePasswordConfirmation, AppResources.Yes,
AppResources.Cancel);
if(!confirmed)
{
return;
}
_googleAnalyticsService.TrackAppEvent("OpenedSetting", "ChangePassword");
Device.OpenUri(new Uri("https://help.bitwarden.com/article/change-your-master-password/"));
}
private async void ChangeEmailCell_Tapped(object sender, EventArgs e)
{
var confirmed = await DisplayAlert(null, AppResources.ChangeEmailConfirmation, AppResources.Yes,
AppResources.Cancel);
if(!confirmed)
{
return;
}
_googleAnalyticsService.TrackAppEvent("OpenedSetting", "ChangeEmail");
Device.OpenUri(new Uri("https://help.bitwarden.com/article/change-your-email/"));
}
private void FingerprintCell_Changed(object sender, EventArgs e)
{
var cell = sender as ExtendedSwitchCell;
if(cell == null)
{
return;
}
_settings.AddOrUpdateValue(Constants.SettingFingerprintUnlockOn, cell.On);
if(cell.On)
{
_settings.AddOrUpdateValue(Constants.SettingPinUnlockOn, false);
PinCell.On = false;
}
}
private void PinCell_Changed(object sender, EventArgs e)
{
var cell = sender as ExtendedSwitchCell;
if(cell == null)
{
return;
}
if(cell.On && !_settings.GetValueOrDefault(Constants.SettingPinUnlockOn, false))
{
cell.On = false;
var pinPage = new SettingsPinPage((page) => PinEntered(page));
Navigation.PushModalAsync(new ExtendedNavigationPage(pinPage));
}
else if(!cell.On)
{
_settings.AddOrUpdateValue(Constants.SettingPinUnlockOn, false);
}
}
private void PinEntered(SettingsPinPage page)
{
page.PinControl.Entry.Unfocus();
page.Navigation.PopModalAsync();
_authService.PIN = page.Model.PIN;
_settings.AddOrUpdateValue(Constants.SettingPinUnlockOn, true);
_settings.AddOrUpdateValue(Constants.SettingFingerprintUnlockOn, false);
PinCell.On = true;
if(FingerprintCell != null)
{
FingerprintCell.On = false;
}
}
private void OptionsCell_Tapped(object sender, EventArgs e)
{
Navigation.PushModalAsync(new ExtendedNavigationPage(new SettingsOptionsPage()));
}
private void FoldersCell_Tapped(object sender, EventArgs e)
{
Navigation.PushModalAsync(new ExtendedNavigationPage(new SettingsListFoldersPage()));
}
private string GetLockOptionsDetailsText()
{
var lockSeconds = _settings.GetValueOrDefault(Constants.SettingLockSeconds, 60 * 15);
if(lockSeconds == -1)
{
return AppResources.Never;
}
else if(lockSeconds == 60)
{
return AppResources.LockOption1Minute;
}
else if(lockSeconds == 60 * 15)
{
return AppResources.LockOption15Minutes;
}
else if(lockSeconds == 60 * 60)
{
return AppResources.LockOption1Hour;
}
else if(lockSeconds == 60 * 60 * 4)
{
return AppResources.LockOption4Hours;
}
else
{
return AppResources.LockOptionImmediately;
}
}
private class CustomTable : ExtendedTableView
{
public CustomTable()
{
Intent = TableIntent.Settings;
HasUnevenRows = true;
if(Device.RuntimePlatform == Device.iOS)
{
RowHeight = -1;
EstimatedRowHeight = 44;
}
else if(Device.RuntimePlatform == Device.Android)
{
BottomPadding = 50;
}
}
}
private class LongDetailViewCell : ExtendedViewCell
{
public LongDetailViewCell(string labelText, string detailText)
{
Label = new Label
{
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
VerticalOptions = LayoutOptions.CenterAndExpand,
LineBreakMode = LineBreakMode.TailTruncation,
Text = labelText
};
Detail = new Label
{
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
LineBreakMode = LineBreakMode.WordWrap,
VerticalOptions = LayoutOptions.End,
Style = (Style)Application.Current.Resources["text-muted"],
Text = detailText
};
var labelDetailStackLayout = new StackLayout
{
HorizontalOptions = LayoutOptions.StartAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
Children = { Label, Detail },
Padding = new Thickness(15)
};
ShowDisclousure = true;
View = labelDetailStackLayout;
}
public Label Label { get; set; }
public Label Detail { get; set; }
}
}
}

View File

@@ -1,92 +0,0 @@
using System;
using Bit.App.Resources;
using Xamarin.Forms;
using XLabs.Ioc;
using Plugin.Settings.Abstractions;
using Bit.App.Models.Page;
using Bit.App.Controls;
namespace Bit.App.Pages
{
public class SettingsPinPage : ExtendedContentPage
{
private readonly ISettings _settings;
private Action<SettingsPinPage> _pinEnteredAction;
public SettingsPinPage(Action<SettingsPinPage> pinEnteredAction)
{
_pinEnteredAction = pinEnteredAction;
_settings = Resolver.Resolve<ISettings>();
Init();
}
public PinPageModel Model { get; set; } = new PinPageModel();
public PinControl PinControl { get; set; }
public TapGestureRecognizer Tgr { get; set; }
public void Init()
{
var instructionLabel = new Label
{
Text = AppResources.SetPINDirection,
LineBreakMode = LineBreakMode.WordWrap,
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
HorizontalTextAlignment = TextAlignment.Center,
Style = (Style)Application.Current.Resources["text-muted"]
};
PinControl = new PinControl();
PinControl.Label.SetBinding(Label.TextProperty, nameof(PinPageModel.LabelText));
PinControl.Entry.SetBinding(Entry.TextProperty, nameof(PinPageModel.PIN));
var stackLayout = new StackLayout
{
Padding = new Thickness(30, 40),
Spacing = 20,
Children = { PinControl.Label, instructionLabel, PinControl.Entry }
};
Tgr = new TapGestureRecognizer();
PinControl.Label.GestureRecognizers.Add(Tgr);
instructionLabel.GestureRecognizers.Add(Tgr);
if(Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.UWP)
{
ToolbarItems.Add(new DismissModalToolBarItem(this, AppResources.Cancel));
}
Title = AppResources.SetPIN;
Content = stackLayout;
Content.GestureRecognizers.Add(Tgr);
BindingContext = Model;
}
protected override void OnAppearing()
{
base.OnAppearing();
Tgr.Tapped += Tgr_Tapped;
PinControl.OnPinEntered += PinEntered;
PinControl.InitEvents();
PinControl.Entry.FocusWithDelay();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
PinControl.Dispose();
Tgr.Tapped -= Tgr_Tapped;
PinControl.OnPinEntered -= PinEntered;
}
protected void PinEntered(object sender, EventArgs args)
{
_pinEnteredAction?.Invoke(this);
}
private void Tgr_Tapped(object sender, EventArgs e)
{
PinControl.Entry.Focus();
}
}
}

View File

@@ -1,122 +0,0 @@
using System;
using System.Threading.Tasks;
using Bit.App.Abstractions;
using Bit.App.Controls;
using Bit.App.Resources;
using Plugin.Connectivity.Abstractions;
using Xamarin.Forms;
using XLabs.Ioc;
using Plugin.Settings.Abstractions;
namespace Bit.App.Pages
{
public class SettingsSyncPage : ExtendedContentPage
{
private readonly ISyncService _syncService;
private readonly IDeviceActionService _deviceActionService;
private readonly IConnectivity _connectivity;
private readonly ISettings _settings;
private readonly IGoogleAnalyticsService _googleAnalyticsService;
public SettingsSyncPage()
{
_syncService = Resolver.Resolve<ISyncService>();
_deviceActionService = Resolver.Resolve<IDeviceActionService>();
_connectivity = Resolver.Resolve<IConnectivity>();
_settings = Resolver.Resolve<ISettings>();
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
Init();
}
public Label LastSyncLabel { get; set; }
public void Init()
{
var syncButton = new ExtendedButton
{
Text = AppResources.SyncVaultNow,
Command = new Command(async () => await SyncAsync()),
Style = (Style)Application.Current.Resources["btn-primaryAccent"]
};
LastSyncLabel = new Label
{
Style = (Style)Application.Current.Resources["text-muted"],
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
HorizontalTextAlignment = TextAlignment.Center
};
SetLastSync();
var stackLayout = new StackLayout
{
VerticalOptions = LayoutOptions.CenterAndExpand,
Children = { syncButton, LastSyncLabel },
Padding = new Thickness(15, 0)
};
if(Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.UWP)
{
ToolbarItems.Add(new DismissModalToolBarItem(this, AppResources.Close));
}
Title = AppResources.Sync;
Content = stackLayout;
}
protected override void OnAppearing()
{
base.OnAppearing();
}
private void SetLastSync()
{
DateTime? lastSyncDate = null;
if(_settings.Contains(Constants.LastSync))
{
lastSyncDate = _settings.GetValueOrDefault(Constants.LastSync, DateTime.UtcNow);
}
try
{
LastSyncLabel.Text = AppResources.LastSync + " " + lastSyncDate?.ToLocalTime().ToString() ?? AppResources.Never;
}
catch
{
// some users with different calendars have issues with ToString()ing a date
// it seems the linker is at fault. just catch for now since this isn't that important.
// ref http://bit.ly/2c2JU7b
}
}
public async Task SyncAsync()
{
if(!_connectivity.IsConnected)
{
AlertNoConnection();
return;
}
await _deviceActionService.ShowLoadingAsync(AppResources.Syncing);
var succeeded = await _syncService.FullSyncAsync(true);
await _deviceActionService.HideLoadingAsync();
if(succeeded)
{
_deviceActionService.Toast(AppResources.SyncingComplete);
_googleAnalyticsService.TrackAppEvent("Synced");
}
else
{
_deviceActionService.Toast(AppResources.SyncingFailed);
}
SetLastSync();
}
public void AlertNoConnection()
{
DisplayAlert(AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage,
AppResources.Ok);
}
}
}