mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 23:25:45 +03:00
uris, fields, etc to view page
This commit is contained in:
parent
c2a168c6b7
commit
d7312e2977
7 changed files with 295 additions and 135 deletions
|
@ -42,6 +42,7 @@ namespace Bit.App.Pages
|
|||
protected async override void OnAppearing()
|
||||
{
|
||||
base.OnAppearing();
|
||||
// await _syncService.FullSyncAsync(true);
|
||||
_broadcasterService.Subscribe(nameof(GroupingsPage), async (message) =>
|
||||
{
|
||||
if(message.Command == "syncCompleted")
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
xmlns:views="clr-namespace:Bit.Core.Models.View;assembly=BitwardenCore"
|
||||
x:DataType="pages:ViewPageViewModel"
|
||||
x:Name="_page"
|
||||
Title="{Binding PageTitle}">
|
||||
<ContentPage.BindingContext>
|
||||
<pages:ViewPageViewModel />
|
||||
|
@ -17,130 +19,241 @@
|
|||
Text="{u:I18n Edit}" />
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<StackLayout StyleClass="box">
|
||||
<StackLayout StyleClass="box-row-header">
|
||||
<Label Text="{u:I18n ItemInformation}"
|
||||
StyleClass="box-header, box-header-platform" />
|
||||
<ScrollView>
|
||||
<StackLayout Spacing="20">
|
||||
<StackLayout StyleClass="box">
|
||||
<StackLayout StyleClass="box-row-header">
|
||||
<Label Text="{u:I18n ItemInformation}"
|
||||
StyleClass="box-header, box-header-platform" />
|
||||
</StackLayout>
|
||||
<StackLayout StyleClass="box-row">
|
||||
<Label
|
||||
Text="{u:I18n Name}"
|
||||
StyleClass="box-label" />
|
||||
<Label
|
||||
Text="{Binding Cipher.Name, Mode=OneWay}"
|
||||
StyleClass="box-value" />
|
||||
</StackLayout>
|
||||
<BoxView StyleClass="box-row-separator" />
|
||||
<StackLayout IsVisible="{Binding IsLogin}"
|
||||
Spacing="0"
|
||||
Padding="0">
|
||||
<Grid StyleClass="box-row">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
Text="{u:I18n Username}"
|
||||
StyleClass="box-label"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0" />
|
||||
<Label
|
||||
Text="{Binding Cipher.Login.Username, Mode=OneWay}"
|
||||
StyleClass="box-value"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0" />
|
||||
<controls:FaButton
|
||||
StyleClass="box-row-button, box-row-button-platform"
|
||||
Text=""
|
||||
Command="{Binding CopyCommand}"
|
||||
CommandParameter="LoginUsername"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Grid.RowSpan="2" />
|
||||
</Grid>
|
||||
<BoxView StyleClass="box-row-separator" />
|
||||
<Grid StyleClass="box-row">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
Text="{u:I18n Password}"
|
||||
StyleClass="box-label"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0" />
|
||||
<Label
|
||||
Text="{Binding Cipher.Login.MaskedPassword, Mode=OneWay}"
|
||||
StyleClass="box-value"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0" />
|
||||
<controls:FaButton
|
||||
StyleClass="box-row-button, box-row-button-platform"
|
||||
Text=""
|
||||
Command="{Binding CopyCommand}"
|
||||
CommandParameter="LoginPassword"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Grid.RowSpan="2" />
|
||||
</Grid>
|
||||
<BoxView StyleClass="box-row-separator" />
|
||||
<Grid StyleClass="box-row" IsVisible="{Binding ShowTotp}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
Text="{u:I18n VerificationCodeTotp}"
|
||||
StyleClass="box-label"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0" />
|
||||
<Label
|
||||
Text="{Binding TotpCodeFormatted, Mode=OneWay}"
|
||||
StyleClass="box-value"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0" />
|
||||
<Label
|
||||
Text="{Binding TotpSec, Mode=OneWay}"
|
||||
Style="{DynamicResource textTotp}"
|
||||
Margin="0, 0, 10, 0"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Grid.RowSpan="2"
|
||||
HorizontalOptions="End"
|
||||
HorizontalTextAlignment="End"
|
||||
VerticalOptions="CenterAndExpand"/>
|
||||
<controls:FaButton
|
||||
StyleClass="box-row-button, box-row-button-platform"
|
||||
Text=""
|
||||
Command="{Binding CopyCommand}"
|
||||
CommandParameter="LoginTotp"
|
||||
Grid.Row="0"
|
||||
Grid.Column="2"
|
||||
Grid.RowSpan="2" />
|
||||
</Grid>
|
||||
<BoxView StyleClass="box-row-separator" IsVisible="{Binding ShowTotp}" />
|
||||
</StackLayout>
|
||||
<StackLayout IsVisible="{Binding IsCard}">
|
||||
|
||||
</StackLayout>
|
||||
<StackLayout IsVisible="{Binding IsIdentity}">
|
||||
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
<StackLayout StyleClass="box" IsVisible="{Binding ShowUris}">
|
||||
<StackLayout StyleClass="box-row-header">
|
||||
<Label Text="{u:I18n URIs}"
|
||||
StyleClass="box-header, box-header-platform" />
|
||||
</StackLayout>
|
||||
<controls:RepeaterView ItemsSource="{Binding Cipher.Login.Uris}">
|
||||
<controls:RepeaterView.ItemTemplate>
|
||||
<DataTemplate x:DataType="views:LoginUriView">
|
||||
<StackLayout Spacing="0" Padding="0">
|
||||
<Grid StyleClass="box-row">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
Text="{u:I18n URI}"
|
||||
StyleClass="box-label"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0" />
|
||||
<Label
|
||||
Text="{Binding HostnameOrUri, Mode=OneWay}"
|
||||
StyleClass="box-value"
|
||||
LineBreakMode="CharacterWrap"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0" />
|
||||
<controls:FaButton
|
||||
StyleClass="box-row-button, box-row-button-platform"
|
||||
Text=""
|
||||
Command="{Binding BindingContext.LaunchUriCommand, Source={x:Reference _page}}"
|
||||
CommandParameter="{Binding .}"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Grid.RowSpan="2" />
|
||||
<controls:FaButton
|
||||
StyleClass="box-row-button, box-row-button-platform"
|
||||
Text=""
|
||||
Command="{Binding BindingContext.CopyUriCommand, Source={x:Reference _page}}"
|
||||
CommandParameter="{Binding .}"
|
||||
Grid.Row="0"
|
||||
Grid.Column="2"
|
||||
Grid.RowSpan="2" />
|
||||
</Grid>
|
||||
<BoxView StyleClass="box-row-separator" />
|
||||
</StackLayout>
|
||||
</DataTemplate>
|
||||
</controls:RepeaterView.ItemTemplate>
|
||||
</controls:RepeaterView>
|
||||
</StackLayout>
|
||||
<StackLayout StyleClass="box" IsVisible="{Binding ShowNotes}">
|
||||
<StackLayout StyleClass="box-row-header">
|
||||
<Label Text="{u:I18n Notes}"
|
||||
StyleClass="box-header, box-header-platform" />
|
||||
</StackLayout>
|
||||
<StackLayout StyleClass="box-row">
|
||||
<Label
|
||||
Text="{Binding Cipher.Notes, Mode=OneWay}"
|
||||
StyleClass="box-value"
|
||||
LineBreakMode="WordWrap" />
|
||||
</StackLayout>
|
||||
<BoxView StyleClass="box-row-separator" />
|
||||
</StackLayout>
|
||||
<StackLayout StyleClass="box" IsVisible="{Binding ShowFields}">
|
||||
<StackLayout StyleClass="box-row-header">
|
||||
<Label Text="{u:I18n CustomFields}"
|
||||
StyleClass="box-header, box-header-platform" />
|
||||
</StackLayout>
|
||||
<controls:RepeaterView ItemsSource="{Binding Cipher.Fields}">
|
||||
<controls:RepeaterView.ItemTemplate>
|
||||
<DataTemplate x:DataType="views:FieldView">
|
||||
<StackLayout Spacing="0" Padding="0">
|
||||
<Grid StyleClass="box-row">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
Text="{Binding Name, Mode=OneWay}"
|
||||
StyleClass="box-label"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0" />
|
||||
<Label
|
||||
Text="{Binding Value, Mode=OneWay}"
|
||||
StyleClass="box-value"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0" />
|
||||
<controls:FaButton
|
||||
StyleClass="box-row-button, box-row-button-platform"
|
||||
Text=""
|
||||
Command="{Binding BindingContext.CopyFieldCommand, Source={x:Reference _page}}"
|
||||
CommandParameter="{Binding .}"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Grid.RowSpan="2" />
|
||||
</Grid>
|
||||
<BoxView StyleClass="box-row-separator" />
|
||||
</StackLayout>
|
||||
</DataTemplate>
|
||||
</controls:RepeaterView.ItemTemplate>
|
||||
</controls:RepeaterView>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
<StackLayout StyleClass="box-row">
|
||||
<Label
|
||||
Text="{u:I18n Name}"
|
||||
StyleClass="box-label" />
|
||||
<Label
|
||||
Text="{Binding Cipher.Name, Mode=OneWay}"
|
||||
StyleClass="box-value" />
|
||||
</StackLayout>
|
||||
<BoxView StyleClass="box-row-separator" />
|
||||
<StackLayout IsVisible="{Binding IsLogin}">
|
||||
<Grid StyleClass="box-row">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
Text="{u:I18n Username}"
|
||||
StyleClass="box-label"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0" />
|
||||
<Label
|
||||
Text="{Binding Cipher.Login.Username, Mode=OneWay}"
|
||||
StyleClass="box-value"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0" />
|
||||
<controls:FaButton StyleClass="box-row-button, box-row-button-platform"
|
||||
Text=""
|
||||
Command="{Binding CopyCommand}"
|
||||
CommandParameter="LoginUsername"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Grid.RowSpan="2" />
|
||||
</Grid>
|
||||
<BoxView StyleClass="box-row-separator" />
|
||||
<Grid StyleClass="box-row">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
Text="{u:I18n Password}"
|
||||
StyleClass="box-label"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0" />
|
||||
<Label
|
||||
Text="{Binding Cipher.Login.MaskedPassword, Mode=OneWay}"
|
||||
StyleClass="box-value"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0" />
|
||||
<controls:FaButton StyleClass="box-row-button, box-row-button-platform"
|
||||
Text=""
|
||||
Command="{Binding CopyCommand}"
|
||||
CommandParameter="LoginPassword"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Grid.RowSpan="2" />
|
||||
</Grid>
|
||||
<BoxView StyleClass="box-row-separator" />
|
||||
<Grid StyleClass="box-row">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
Text="{u:I18n VerificationCodeTotp}"
|
||||
StyleClass="box-label"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0" />
|
||||
<Label
|
||||
Text="{Binding TotpCodeFormatted, Mode=OneWay}"
|
||||
StyleClass="box-value"
|
||||
Grid.Row="1"
|
||||
Grid.Column="0" />
|
||||
<Label
|
||||
Text="{Binding TotpSec, Mode=OneWay}"
|
||||
Style="{DynamicResource textTotp}"
|
||||
Margin="0, 0, 10, 0"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Grid.RowSpan="2"
|
||||
HorizontalOptions="End"
|
||||
HorizontalTextAlignment="End"
|
||||
VerticalOptions="CenterAndExpand"/>
|
||||
<controls:FaButton StyleClass="box-row-button, box-row-button-platform"
|
||||
Text=""
|
||||
Command="{Binding CopyCommand}"
|
||||
CommandParameter="LoginTotp"
|
||||
Grid.Row="0"
|
||||
Grid.Column="2"
|
||||
Grid.RowSpan="2" />
|
||||
</Grid>
|
||||
</StackLayout>
|
||||
<StackLayout IsVisible="{Binding IsCard}">
|
||||
|
||||
</StackLayout>
|
||||
<StackLayout IsVisible="{Binding IsIdentity}">
|
||||
|
||||
</StackLayout>
|
||||
<StackLayout StyleClass="box-row">
|
||||
<Label
|
||||
Text="{u:I18n Notes}"
|
||||
StyleClass="box-label" />
|
||||
<Label
|
||||
Text="{Binding Cipher.Notes, Mode=OneWay}"
|
||||
StyleClass="box-value" />
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
|
||||
</ContentPage>
|
||||
|
|
|
@ -31,12 +31,16 @@ namespace Bit.App.Pages
|
|||
_userService = ServiceContainer.Resolve<IUserService>("userService");
|
||||
_totpService = ServiceContainer.Resolve<ITotpService>("totpService");
|
||||
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
||||
CopyCommand = new Command<string>(CopyAsync);
|
||||
CopyCommand = new Command<string>((id) => CopyAsync(id, null));
|
||||
CopyUriCommand = new Command<LoginUriView>(CopyUriAsync);
|
||||
LaunchUriCommand = new Command<LoginUriView>(LaunchUriAsync);
|
||||
|
||||
PageTitle = AppResources.ViewItem;
|
||||
}
|
||||
|
||||
public Command CopyCommand { get; set; }
|
||||
public Command CopyUriCommand { get; set; }
|
||||
public Command LaunchUriCommand { get; set; }
|
||||
public string CipherId { get; set; }
|
||||
public CipherView Cipher
|
||||
{
|
||||
|
@ -47,7 +51,11 @@ namespace Bit.App.Pages
|
|||
nameof(IsLogin),
|
||||
nameof(IsIdentity),
|
||||
nameof(IsCard),
|
||||
nameof(IsSecureNote)
|
||||
nameof(IsSecureNote),
|
||||
nameof(ShowUris),
|
||||
nameof(ShowFields),
|
||||
nameof(ShowNotes),
|
||||
nameof(ShowTotp)
|
||||
});
|
||||
}
|
||||
public bool CanAccessPremium
|
||||
|
@ -59,10 +67,19 @@ namespace Bit.App.Pages
|
|||
public bool IsIdentity => _cipher?.Type == Core.Enums.CipherType.Identity;
|
||||
public bool IsCard => _cipher?.Type == Core.Enums.CipherType.Card;
|
||||
public bool IsSecureNote => _cipher?.Type == Core.Enums.CipherType.SecureNote;
|
||||
public bool ShowUris => IsLogin && _cipher.Login.HasUris;
|
||||
public bool ShowNotes => !string.IsNullOrWhiteSpace(_cipher.Notes);
|
||||
public bool ShowFields => _cipher.HasFields;
|
||||
public bool ShowTotp => !string.IsNullOrWhiteSpace(_cipher.Login.Totp) &&
|
||||
!string.IsNullOrWhiteSpace(TotpCodeFormatted);
|
||||
public string TotpCodeFormatted
|
||||
{
|
||||
get => _totpCodeFormatted;
|
||||
set => SetProperty(ref _totpCodeFormatted, value);
|
||||
set => SetProperty(ref _totpCodeFormatted, value,
|
||||
additionalPropertyNames: new string[]
|
||||
{
|
||||
nameof(ShowTotp)
|
||||
});
|
||||
}
|
||||
public string TotpSec
|
||||
{
|
||||
|
@ -151,9 +168,8 @@ namespace Bit.App.Pages
|
|||
}
|
||||
}
|
||||
|
||||
private async void CopyAsync(string id)
|
||||
private async void CopyAsync(string id, string text = null)
|
||||
{
|
||||
string text = null;
|
||||
string name = null;
|
||||
if(id == "LoginUsername")
|
||||
{
|
||||
|
@ -170,6 +186,10 @@ namespace Bit.App.Pages
|
|||
text = _totpCode;
|
||||
name = AppResources.VerificationCodeTotp;
|
||||
}
|
||||
else if(id == "LoginUri")
|
||||
{
|
||||
name = AppResources.URI;
|
||||
}
|
||||
|
||||
if(text != null)
|
||||
{
|
||||
|
@ -180,5 +200,18 @@ namespace Bit.App.Pages
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CopyUriAsync(LoginUriView uri)
|
||||
{
|
||||
CopyAsync("LoginUri", uri.Uri);
|
||||
}
|
||||
|
||||
private void LaunchUriAsync(LoginUriView uri)
|
||||
{
|
||||
if(uri.CanLaunch)
|
||||
{
|
||||
_platformUtilsService.LaunchUri(uri.LaunchUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
9
src/App/Resources/AppResources.Designer.cs
generated
9
src/App/Resources/AppResources.Designer.cs
generated
|
@ -3246,6 +3246,15 @@ namespace Bit.App.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to URIs.
|
||||
/// </summary>
|
||||
internal static string URIs {
|
||||
get {
|
||||
return ResourceManager.GetString("URIs", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Use another two-step login method.
|
||||
/// </summary>
|
||||
|
|
|
@ -1364,4 +1364,8 @@
|
|||
<data name="AllItems" xml:space="preserve">
|
||||
<value>All Items</value>
|
||||
</data>
|
||||
<data name="URIs" xml:space="preserve">
|
||||
<value>URIs</value>
|
||||
<comment>Plural form of a URI</comment>
|
||||
</data>
|
||||
</root>
|
|
@ -40,8 +40,8 @@
|
|||
ApplyToDerivedTypes="True"
|
||||
Class="box-row-button-platform">
|
||||
<Setter Property="WidthRequest"
|
||||
Value="40" />
|
||||
Value="37" />
|
||||
<Setter Property="FontSize"
|
||||
Value="28" />
|
||||
Value="25" />
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
|
|
|
@ -19,11 +19,11 @@ namespace Bit.Core.Models.View
|
|||
public DateTime? PasswordRevisionDate { get; set; }
|
||||
public string Totp { get; set; }
|
||||
public List<LoginUriView> Uris { get; set; }
|
||||
public string Uri => HashUris ? Uris[0].Uri : null;
|
||||
public string Uri => HasUris ? Uris[0].Uri : null;
|
||||
public string MaskedPassword => Password != null ? "••••••••" : null;
|
||||
public string SubTitle => Username;
|
||||
public bool CanLaunch => HashUris && Uris.Any(u => u.CanLaunch);
|
||||
public string LaunchUri => HashUris ? Uris.FirstOrDefault(u => u.CanLaunch)?.LaunchUri : null;
|
||||
public bool HashUris => (Uris?.Count ?? 0) > 0;
|
||||
public bool CanLaunch => HasUris && Uris.Any(u => u.CanLaunch);
|
||||
public string LaunchUri => HasUris ? Uris.FirstOrDefault(u => u.CanLaunch)?.LaunchUri : null;
|
||||
public bool HasUris => (Uris?.Count ?? 0) > 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue