mirror of
https://github.com/bitwarden/android.git
synced 2024-12-25 18:38:27 +03:00
handle conditions when no data
This commit is contained in:
parent
b07dc8443e
commit
92b7b1d603
4 changed files with 86 additions and 24 deletions
|
@ -56,11 +56,12 @@ namespace Bit.App.Pages
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExtendedObservableCollection<Section<Cipher>> PresentationLetters { get; private set; }
|
public ExtendedObservableCollection<Section<Cipher>> PresentationSections { get; private set; }
|
||||||
= new ExtendedObservableCollection<Section<Cipher>>();
|
= new ExtendedObservableCollection<Section<Cipher>>();
|
||||||
public Cipher[] Ciphers { get; set; } = new Cipher[] { };
|
public Cipher[] Ciphers { get; set; } = new Cipher[] { };
|
||||||
public ListView ListView { get; set; }
|
public ListView ListView { get; set; }
|
||||||
public SearchBar Search { get; set; }
|
public SearchBar Search { get; set; }
|
||||||
|
public StackLayout NoDataStackLayout { get; set; }
|
||||||
public StackLayout ResultsStackLayout { get; set; }
|
public StackLayout ResultsStackLayout { get; set; }
|
||||||
private AddCipherToolBarItem AddCipherItem { get; set; }
|
private AddCipherToolBarItem AddCipherItem { get; set; }
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ namespace Bit.App.Pages
|
||||||
ListView = new ListView(ListViewCachingStrategy.RecycleElement)
|
ListView = new ListView(ListViewCachingStrategy.RecycleElement)
|
||||||
{
|
{
|
||||||
IsGroupingEnabled = true,
|
IsGroupingEnabled = true,
|
||||||
ItemsSource = PresentationLetters,
|
ItemsSource = PresentationSections,
|
||||||
HasUnevenRows = true,
|
HasUnevenRows = true,
|
||||||
GroupHeaderTemplate = new DataTemplate(() => new SectionHeaderViewCell(nameof(Section<Cipher>.Name),
|
GroupHeaderTemplate = new DataTemplate(() => new SectionHeaderViewCell(nameof(Section<Cipher>.Name),
|
||||||
nameof(Section<Cipher>.Count))),
|
nameof(Section<Cipher>.Count))),
|
||||||
|
@ -101,6 +102,41 @@ namespace Bit.App.Pages
|
||||||
Search.HeightRequest = 50;
|
Search.HeightRequest = 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var noDataLabel = new Label
|
||||||
|
{
|
||||||
|
Text = _favorites ? AppResources.NoFavorites : AppResources.NoItems,
|
||||||
|
HorizontalTextAlignment = TextAlignment.Center,
|
||||||
|
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
|
||||||
|
Style = (Style)Application.Current.Resources["text-muted"]
|
||||||
|
};
|
||||||
|
|
||||||
|
if(_folder || !string.IsNullOrWhiteSpace(_folderId))
|
||||||
|
{
|
||||||
|
noDataLabel.Text = AppResources.NoItemsFolder;
|
||||||
|
}
|
||||||
|
else if(!string.IsNullOrWhiteSpace(_collectionId))
|
||||||
|
{
|
||||||
|
noDataLabel.Text = AppResources.NoItemsCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
NoDataStackLayout = new StackLayout
|
||||||
|
{
|
||||||
|
Children = { noDataLabel },
|
||||||
|
VerticalOptions = LayoutOptions.CenterAndExpand,
|
||||||
|
Padding = new Thickness(20, 0),
|
||||||
|
Spacing = 20
|
||||||
|
};
|
||||||
|
|
||||||
|
if(string.IsNullOrWhiteSpace(_collectionId) && !_favorites)
|
||||||
|
{
|
||||||
|
NoDataStackLayout.Children.Add(new ExtendedButton
|
||||||
|
{
|
||||||
|
Text = AppResources.AddAnItem,
|
||||||
|
Command = new Command(() => Helpers.AddCipher(this, _folderId)),
|
||||||
|
Style = (Style)Application.Current.Resources["btn-primaryAccent"]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
ResultsStackLayout = new StackLayout
|
ResultsStackLayout = new StackLayout
|
||||||
{
|
{
|
||||||
Children = { Search, ListView },
|
Children = { Search, ListView },
|
||||||
|
@ -182,7 +218,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
if(string.IsNullOrWhiteSpace(searchFilter))
|
if(string.IsNullOrWhiteSpace(searchFilter))
|
||||||
{
|
{
|
||||||
LoadLetters(Ciphers, ct);
|
LoadSections(Ciphers, ct);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -194,7 +230,7 @@ namespace Bit.App.Pages
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
ct.ThrowIfCancellationRequested();
|
ct.ThrowIfCancellationRequested();
|
||||||
LoadLetters(filteredCiphers, ct);
|
LoadSections(filteredCiphers, ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +284,7 @@ namespace Bit.App.Pages
|
||||||
private CancellationTokenSource FetchAndLoadVault()
|
private CancellationTokenSource FetchAndLoadVault()
|
||||||
{
|
{
|
||||||
var cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
if(PresentationLetters.Count > 0 && _syncService.SyncInProgress)
|
if(PresentationSections.Count > 0 && _syncService.SyncInProgress)
|
||||||
{
|
{
|
||||||
return cts;
|
return cts;
|
||||||
}
|
}
|
||||||
|
@ -281,7 +317,7 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
// Sort numbers and letters before special characters
|
// Sort numbers and letters before special characters
|
||||||
return !string.IsNullOrWhiteSpace(s.Name) && s.Name.Length > 0 &&
|
return !string.IsNullOrWhiteSpace(s.Name) && s.Name.Length > 0 &&
|
||||||
Char.IsLetterOrDigit(s.Name[0]) ? 0 : 1;
|
Char.IsDigit(s.Name[0]) ? 0 : Char.IsLetter(s.Name[0]) ? 1 : 2;
|
||||||
})
|
})
|
||||||
.ThenBy(s => s.Name)
|
.ThenBy(s => s.Name)
|
||||||
.ThenBy(s => s.Subtitle)
|
.ThenBy(s => s.Subtitle)
|
||||||
|
@ -297,15 +333,22 @@ namespace Bit.App.Pages
|
||||||
return cts;
|
return cts;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadLetters(Cipher[] ciphers, CancellationToken ct)
|
private void LoadSections(Cipher[] ciphers, CancellationToken ct)
|
||||||
{
|
{
|
||||||
ct.ThrowIfCancellationRequested();
|
ct.ThrowIfCancellationRequested();
|
||||||
var letterGroups = ciphers.GroupBy(c => c.NameGroup).Select(g => new Section<Cipher>(g.ToList(), g.Key));
|
var sections = ciphers.GroupBy(c => c.NameGroup).Select(g => new Section<Cipher>(g.ToList(), g.Key));
|
||||||
ct.ThrowIfCancellationRequested();
|
ct.ThrowIfCancellationRequested();
|
||||||
Device.BeginInvokeOnMainThread(() =>
|
Device.BeginInvokeOnMainThread(() =>
|
||||||
{
|
{
|
||||||
PresentationLetters.ResetWithRange(letterGroups);
|
PresentationSections.ResetWithRange(sections);
|
||||||
|
if(PresentationSections.Count > 0 || !string.IsNullOrWhiteSpace(Search.Text))
|
||||||
|
{
|
||||||
Content = ResultsStackLayout;
|
Content = ResultsStackLayout;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Content = NoDataStackLayout;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,14 +90,6 @@ namespace Bit.App.Pages
|
||||||
Style = (Style)Application.Current.Resources["text-muted"]
|
Style = (Style)Application.Current.Resources["text-muted"]
|
||||||
};
|
};
|
||||||
|
|
||||||
NoDataStackLayout = new StackLayout
|
|
||||||
{
|
|
||||||
Children = { noDataLabel },
|
|
||||||
VerticalOptions = LayoutOptions.CenterAndExpand,
|
|
||||||
Padding = new Thickness(20, 0),
|
|
||||||
Spacing = 20
|
|
||||||
};
|
|
||||||
|
|
||||||
var addCipherButton = new ExtendedButton
|
var addCipherButton = new ExtendedButton
|
||||||
{
|
{
|
||||||
Text = AppResources.AddAnItem,
|
Text = AppResources.AddAnItem,
|
||||||
|
@ -105,7 +97,13 @@ namespace Bit.App.Pages
|
||||||
Style = (Style)Application.Current.Resources["btn-primaryAccent"]
|
Style = (Style)Application.Current.Resources["btn-primaryAccent"]
|
||||||
};
|
};
|
||||||
|
|
||||||
NoDataStackLayout.Children.Add(addCipherButton);
|
NoDataStackLayout = new StackLayout
|
||||||
|
{
|
||||||
|
Children = { noDataLabel, addCipherButton },
|
||||||
|
VerticalOptions = LayoutOptions.CenterAndExpand,
|
||||||
|
Padding = new Thickness(20, 0),
|
||||||
|
Spacing = 20
|
||||||
|
};
|
||||||
|
|
||||||
LoadingIndicator = new ActivityIndicator
|
LoadingIndicator = new ActivityIndicator
|
||||||
{
|
{
|
||||||
|
@ -224,13 +222,10 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
|
|
||||||
Device.BeginInvokeOnMainThread(() =>
|
Device.BeginInvokeOnMainThread(() =>
|
||||||
{
|
|
||||||
if(sections.Any())
|
|
||||||
{
|
{
|
||||||
PresentationSections.ResetWithRange(sections);
|
PresentationSections.ResetWithRange(sections);
|
||||||
}
|
|
||||||
|
|
||||||
if(PresentationSections.Count > 0)
|
if(ciphers.Any() || folders.Any())
|
||||||
{
|
{
|
||||||
Content = ListView;
|
Content = ListView;
|
||||||
}
|
}
|
||||||
|
|
18
src/App/Resources/AppResources.Designer.cs
generated
18
src/App/Resources/AppResources.Designer.cs
generated
|
@ -2113,6 +2113,24 @@ namespace Bit.App.Resources {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to There are no items in this collection..
|
||||||
|
/// </summary>
|
||||||
|
public static string NoItemsCollection {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("NoItemsCollection", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to There are no items in this folder..
|
||||||
|
/// </summary>
|
||||||
|
public static string NoItemsFolder {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("NoItemsFolder", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to There are no items in your vault for {0}..
|
/// Looks up a localized string similar to There are no items in your vault for {0}..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1203,4 +1203,10 @@
|
||||||
<data name="DefaultPageVaultDescription" xml:space="preserve">
|
<data name="DefaultPageVaultDescription" xml:space="preserve">
|
||||||
<value>Default to the "My Vault" page instead of "Favorites" whenever I open the app.</value>
|
<value>Default to the "My Vault" page instead of "Favorites" whenever I open the app.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="NoItemsCollection" xml:space="preserve">
|
||||||
|
<value>There are no items in this collection.</value>
|
||||||
|
</data>
|
||||||
|
<data name="NoItemsFolder" xml:space="preserve">
|
||||||
|
<value>There are no items in this folder.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
Loading…
Reference in a new issue