diff --git a/src/App/App.csproj b/src/App/App.csproj
index 45f805654..a979c09be 100644
--- a/src/App/App.csproj
+++ b/src/App/App.csproj
@@ -38,6 +38,9 @@
GeneratorPage.xaml
+
+ GeneratorHistoryPage.xaml
+
AttachmentsPage.xaml
diff --git a/src/App/Pages/Generator/GeneratorHistoryPage.xaml b/src/App/Pages/Generator/GeneratorHistoryPage.xaml
new file mode 100644
index 000000000..7bd473634
--- /dev/null
+++ b/src/App/Pages/Generator/GeneratorHistoryPage.xaml
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/App/Pages/Generator/GeneratorHistoryPage.xaml.cs b/src/App/Pages/Generator/GeneratorHistoryPage.xaml.cs
new file mode 100644
index 000000000..914afa87e
--- /dev/null
+++ b/src/App/Pages/Generator/GeneratorHistoryPage.xaml.cs
@@ -0,0 +1,30 @@
+using System;
+
+namespace Bit.App.Pages
+{
+ public partial class GeneratorHistoryPage : BaseContentPage
+ {
+ private GeneratorHistoryPageViewModel _vm;
+
+ public GeneratorHistoryPage()
+ {
+ InitializeComponent();
+ SetActivityIndicator();
+ _vm = BindingContext as GeneratorHistoryPageViewModel;
+ _vm.Page = this;
+ }
+
+ protected override async void OnAppearing()
+ {
+ base.OnAppearing();
+ await LoadOnAppearedAsync(_mainLayout, true, async () => {
+ await _vm.InitAsync();
+ });
+ }
+
+ private async void Clear_Clicked(object sender, EventArgs e)
+ {
+ await _vm.ClearAsync();
+ }
+ }
+}
diff --git a/src/App/Pages/Generator/GeneratorHistoryPageViewModel.cs b/src/App/Pages/Generator/GeneratorHistoryPageViewModel.cs
new file mode 100644
index 000000000..ad7f59195
--- /dev/null
+++ b/src/App/Pages/Generator/GeneratorHistoryPageViewModel.cs
@@ -0,0 +1,58 @@
+using Bit.App.Resources;
+using Bit.Core.Abstractions;
+using Bit.Core.Models.Domain;
+using Bit.Core.Utilities;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Xamarin.Forms;
+
+namespace Bit.App.Pages
+{
+ public class GeneratorHistoryPageViewModel : BaseViewModel
+ {
+ private readonly IPlatformUtilsService _platformUtilsService;
+ private readonly IPasswordGenerationService _passwordGenerationService;
+
+ private bool _showNoData;
+
+ public GeneratorHistoryPageViewModel()
+ {
+ _platformUtilsService = ServiceContainer.Resolve("platformUtilsService");
+ _passwordGenerationService = ServiceContainer.Resolve(
+ "passwordGenerationService");
+
+ PageTitle = AppResources.PasswordHistory;
+ History = new ExtendedObservableCollection();
+ CopyCommand = new Command(CopyAsync);
+ }
+
+ public Command CopyCommand { get; set; }
+ public ExtendedObservableCollection History { get; set; }
+
+ public bool ShowNoData
+ {
+ get => _showNoData;
+ set => SetProperty(ref _showNoData, value);
+ }
+
+ public async Task InitAsync()
+ {
+ var history = await _passwordGenerationService.GetHistoryAsync();
+ History.ResetWithRange(history ?? new List());
+ ShowNoData = History.Count == 0;
+ }
+
+ public async Task ClearAsync()
+ {
+ History.ResetWithRange(new List());
+ await _passwordGenerationService.ClearAsync();
+ }
+
+ private async void CopyAsync(GeneratedPasswordHistory ph)
+ {
+ await _platformUtilsService.CopyToClipboardAsync(ph.Password);
+ _platformUtilsService.ShowToast("info", null,
+ string.Format(AppResources.ValueHasBeenCopied, AppResources.Password));
+ }
+ }
+}
diff --git a/src/App/Pages/Generator/GeneratorPage.xaml.cs b/src/App/Pages/Generator/GeneratorPage.xaml.cs
index a31c5fa35..a30a619b3 100644
--- a/src/App/Pages/Generator/GeneratorPage.xaml.cs
+++ b/src/App/Pages/Generator/GeneratorPage.xaml.cs
@@ -1,4 +1,5 @@
using System;
+using Xamarin.Forms;
namespace Bit.App.Pages
{
@@ -44,9 +45,10 @@ namespace Bit.App.Pages
_selectAction?.Invoke(_vm.Password);
}
- private void History_Clicked(object sender, EventArgs e)
+ private async void History_Clicked(object sender, EventArgs e)
{
-
+ var page = new GeneratorHistoryPage();
+ await Navigation.PushModalAsync(new NavigationPage(page));
}
}
}
diff --git a/src/App/Resources/AppResources.Designer.cs b/src/App/Resources/AppResources.Designer.cs
index 42400d59c..d273e376f 100644
--- a/src/App/Resources/AppResources.Designer.cs
+++ b/src/App/Resources/AppResources.Designer.cs
@@ -870,6 +870,15 @@ namespace Bit.App.Resources {
}
}
+ ///
+ /// Looks up a localized string similar to Clear.
+ ///
+ public static string Clear {
+ get {
+ return ResourceManager.GetString("Clear", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Close.
///
diff --git a/src/App/Resources/AppResources.resx b/src/App/Resources/AppResources.resx
index 500d50953..0e2e858f0 100644
--- a/src/App/Resources/AppResources.resx
+++ b/src/App/Resources/AppResources.resx
@@ -1456,4 +1456,8 @@
Word Separator
+
+ Clear
+ To clear something out. example: To clear browser history.
+
\ No newline at end of file
diff --git a/src/App/Utilities/DateTimeConverter.cs b/src/App/Utilities/DateTimeConverter.cs
index bcd9f0258..6022caf2d 100644
--- a/src/App/Utilities/DateTimeConverter.cs
+++ b/src/App/Utilities/DateTimeConverter.cs
@@ -16,7 +16,7 @@ namespace Bit.App.Utilities
{
return string.Empty;
}
- var d = (DateTime)value;
+ var d = ((DateTime)value).ToLocalTime();
return string.Format("{0} {1}", d.ToShortDateString(), d.ToShortTimeString());
}
diff --git a/src/Core/Services/PasswordGenerationService.cs b/src/Core/Services/PasswordGenerationService.cs
index f85beb502..f7c95d080 100644
--- a/src/Core/Services/PasswordGenerationService.cs
+++ b/src/Core/Services/PasswordGenerationService.cs
@@ -248,12 +248,12 @@ namespace Bit.Core.Services
return;
}
var currentHistory = await GetHistoryAsync();
-
// Prevent duplicates
if(MatchesPrevious(password, currentHistory))
{
return;
}
+ currentHistory.Insert(0, new GeneratedPasswordHistory { Password = password, Date = DateTime.UtcNow });
// Remove old items.
if(currentHistory.Count > MaxPasswordsInHistory)
{