mirror of
https://github.com/bitwarden/mobile.git
synced 2024-12-17 15:27:43 +01:00
stub out more add/edit page stuff
This commit is contained in:
parent
13267ff83d
commit
a236d7fbb1
@ -15,8 +15,7 @@
|
|||||||
</ContentPage.BindingContext>
|
</ContentPage.BindingContext>
|
||||||
|
|
||||||
<ContentPage.ToolbarItems>
|
<ContentPage.ToolbarItems>
|
||||||
<ToolbarItem Icon="cogs.png"
|
<ToolbarItem Text="{u:I18n Save}" Clicked="Save_Clicked" />
|
||||||
Text="{u:I18n Edit}" />
|
|
||||||
</ContentPage.ToolbarItems>
|
</ContentPage.ToolbarItems>
|
||||||
|
|
||||||
<ContentPage.Resources>
|
<ContentPage.Resources>
|
||||||
@ -38,564 +37,10 @@
|
|||||||
<Label
|
<Label
|
||||||
Text="{u:I18n Name}"
|
Text="{u:I18n Name}"
|
||||||
StyleClass="box-label" />
|
StyleClass="box-label" />
|
||||||
<Label
|
<Entry
|
||||||
Text="{Binding Cipher.Name, Mode=OneWay}"
|
Text="{Binding Cipher.Name, Mode=OneWay}"
|
||||||
StyleClass="box-value" />
|
StyleClass="box-value" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<BoxView StyleClass="box-row-separator" />
|
|
||||||
<StackLayout IsVisible="{Binding IsLogin}" Spacing="0" Padding="0">
|
|
||||||
<Grid StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Login.Username, Converter={StaticResource stringHasValue}}">
|
|
||||||
<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"
|
|
||||||
IsVisible="{Binding Cipher.Login.Username, Converter={StaticResource stringHasValue}}" />
|
|
||||||
<Grid StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Login.Password, Converter={StaticResource stringHasValue}}">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="*" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n Password}"
|
|
||||||
StyleClass="box-label"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="0" />
|
|
||||||
<controls:MonoLabel
|
|
||||||
Text="{Binding Cipher.Login.MaskedPassword, Mode=OneWay}"
|
|
||||||
StyleClass="box-value"
|
|
||||||
Grid.Row="1"
|
|
||||||
Grid.Column="0"
|
|
||||||
IsVisible="{Binding ShowPassword, Converter={StaticResource inverseBool}}" />
|
|
||||||
<controls:MonoLabel
|
|
||||||
FormattedText="{Binding ColoredPassword, Mode=OneWay}"
|
|
||||||
StyleClass="box-value"
|
|
||||||
Grid.Row="1"
|
|
||||||
Grid.Column="0"
|
|
||||||
IsVisible="{Binding ShowPassword}" />
|
|
||||||
<controls:FaButton
|
|
||||||
StyleClass="box-row-button, box-row-button-platform"
|
|
||||||
Text=""
|
|
||||||
Command="{Binding CheckPasswordCommand}"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="1"
|
|
||||||
Grid.RowSpan="2" />
|
|
||||||
<controls:FaButton
|
|
||||||
StyleClass="box-row-button, box-row-button-platform"
|
|
||||||
Text="{Binding ShowPasswordIcon}"
|
|
||||||
Command="{Binding TogglePasswordCommand}"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="2"
|
|
||||||
Grid.RowSpan="2" />
|
|
||||||
<controls:FaButton
|
|
||||||
StyleClass="box-row-button, box-row-button-platform"
|
|
||||||
Text=""
|
|
||||||
Command="{Binding CopyCommand}"
|
|
||||||
CommandParameter="LoginPassword"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="3"
|
|
||||||
Grid.RowSpan="2" />
|
|
||||||
</Grid>
|
|
||||||
<BoxView StyleClass="box-row-separator"
|
|
||||||
IsVisible="{Binding Cipher.Login.Password, Converter={StaticResource stringHasValue}}" />
|
|
||||||
<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" />
|
|
||||||
<controls:MonoLabel
|
|
||||||
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}" Spacing="0" Padding="0">
|
|
||||||
<StackLayout StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Card.CardholderName, Converter={StaticResource stringHasValue}}">
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n CardholderName}"
|
|
||||||
StyleClass="box-label" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Card.CardholderName, Mode=OneWay}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
</StackLayout>
|
|
||||||
<BoxView StyleClass="box-row-separator"
|
|
||||||
IsVisible="{Binding Cipher.Card.CardholderName, Converter={StaticResource stringHasValue}}"/>
|
|
||||||
<Grid StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Card.Number, Converter={StaticResource stringHasValue}}">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="*" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n Number}"
|
|
||||||
StyleClass="box-label"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="0" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Card.Number, 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="CardNumber"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="1"
|
|
||||||
Grid.RowSpan="2" />
|
|
||||||
</Grid>
|
|
||||||
<BoxView StyleClass="box-row-separator"
|
|
||||||
IsVisible="{Binding Cipher.Card.Number, Converter={StaticResource stringHasValue}}" />
|
|
||||||
<StackLayout StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Card.Brand, Converter={StaticResource stringHasValue}}">
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n Brand}"
|
|
||||||
StyleClass="box-label" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Card.Brand, Mode=OneWay}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
</StackLayout>
|
|
||||||
<BoxView StyleClass="box-row-separator"
|
|
||||||
IsVisible="{Binding Cipher.Card.Brand, Converter={StaticResource stringHasValue}}" />
|
|
||||||
<StackLayout StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Card.Expiration, Converter={StaticResource stringHasValue}}">
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n Expiration}"
|
|
||||||
StyleClass="box-label" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Card.Expiration, Mode=OneWay}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
</StackLayout>
|
|
||||||
<BoxView StyleClass="box-row-separator"
|
|
||||||
IsVisible="{Binding Cipher.Card.Expiration, Converter={StaticResource stringHasValue}}" />
|
|
||||||
<Grid StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Card.Code, Converter={StaticResource stringHasValue}}">
|
|
||||||
<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 SecurityCode}"
|
|
||||||
StyleClass="box-label"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="0" />
|
|
||||||
<controls:MonoLabel
|
|
||||||
Text="{Binding Cipher.Card.MaskedCode, Mode=OneWay}"
|
|
||||||
StyleClass="box-value"
|
|
||||||
Grid.Row="1"
|
|
||||||
Grid.Column="0"
|
|
||||||
IsVisible="{Binding ShowCardCode, Converter={StaticResource inverseBool}}" />
|
|
||||||
<controls:MonoLabel
|
|
||||||
Text="{Binding Cipher.Card.Code, Mode=OneWay}"
|
|
||||||
StyleClass="box-value"
|
|
||||||
Grid.Row="1"
|
|
||||||
Grid.Column="0"
|
|
||||||
IsVisible="{Binding ShowCardCode}" />
|
|
||||||
<controls:FaButton
|
|
||||||
StyleClass="box-row-button, box-row-button-platform"
|
|
||||||
Text="{Binding ShowCardCodeIcon}"
|
|
||||||
Command="{Binding ToggleCardCodeCommand}"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="1"
|
|
||||||
Grid.RowSpan="2" />
|
|
||||||
<controls:FaButton
|
|
||||||
StyleClass="box-row-button, box-row-button-platform"
|
|
||||||
Text=""
|
|
||||||
Command="{Binding CopyCommand}"
|
|
||||||
CommandParameter="CardCode"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="2"
|
|
||||||
Grid.RowSpan="2" />
|
|
||||||
</Grid>
|
|
||||||
<BoxView StyleClass="box-row-separator"
|
|
||||||
IsVisible="{Binding Cipher.Card.Code, Converter={StaticResource stringHasValue}}" />
|
|
||||||
</StackLayout>
|
|
||||||
<StackLayout IsVisible="{Binding IsIdentity}" Spacing="0" Padding="0">
|
|
||||||
<StackLayout StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Identity.FullName, Converter={StaticResource stringHasValue}}">
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n IdentityName}"
|
|
||||||
StyleClass="box-label" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Identity.FullName, Mode=OneWay}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
</StackLayout>
|
|
||||||
<BoxView StyleClass="box-row-separator"
|
|
||||||
IsVisible="{Binding Cipher.Identity.FullName, Converter={StaticResource stringHasValue}}" />
|
|
||||||
<StackLayout StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Identity.Username, Converter={StaticResource stringHasValue}}">
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n Username}"
|
|
||||||
StyleClass="box-label" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Identity.Username, Mode=OneWay}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
</StackLayout>
|
|
||||||
<BoxView StyleClass="box-row-separator"
|
|
||||||
IsVisible="{Binding Cipher.Identity.Username, Converter={StaticResource stringHasValue}}" />
|
|
||||||
<StackLayout StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Identity.Company, Converter={StaticResource stringHasValue}}">
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n Company}"
|
|
||||||
StyleClass="box-label" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Identity.Company, Mode=OneWay}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
</StackLayout>
|
|
||||||
<BoxView StyleClass="box-row-separator"
|
|
||||||
IsVisible="{Binding Cipher.Identity.Company, Converter={StaticResource stringHasValue}}" />
|
|
||||||
<StackLayout StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Identity.SSN, Converter={StaticResource stringHasValue}}">
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n SSN}"
|
|
||||||
StyleClass="box-label" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Identity.SSN, Mode=OneWay}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
</StackLayout>
|
|
||||||
<BoxView StyleClass="box-row-separator"
|
|
||||||
IsVisible="{Binding Cipher.Identity.SSN, Converter={StaticResource stringHasValue}}"/>
|
|
||||||
<StackLayout StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Identity.PassportNumber, Converter={StaticResource stringHasValue}}">
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n PassportNumber}"
|
|
||||||
StyleClass="box-label" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Identity.PassportNumber, Mode=OneWay}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
</StackLayout>
|
|
||||||
<BoxView StyleClass="box-row-separator"
|
|
||||||
IsVisible="{Binding Cipher.Identity.PassportNumber, Converter={StaticResource stringHasValue}}" />
|
|
||||||
<StackLayout StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Identity.LicenseNumber, Converter={StaticResource stringHasValue}}">
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n LicenseNumber}"
|
|
||||||
StyleClass="box-label" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Identity.LicenseNumber, Mode=OneWay}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
</StackLayout>
|
|
||||||
<BoxView StyleClass="box-row-separator"
|
|
||||||
IsVisible="{Binding Cipher.Identity.LicenseNumber, Converter={StaticResource stringHasValue}}" />
|
|
||||||
<StackLayout StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Identity.Email, Converter={StaticResource stringHasValue}}">
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n Email}"
|
|
||||||
StyleClass="box-label" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Identity.Email, Mode=OneWay}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
</StackLayout>
|
|
||||||
<BoxView StyleClass="box-row-separator"
|
|
||||||
IsVisible="{Binding Cipher.Identity.Email, Converter={StaticResource stringHasValue}}" />
|
|
||||||
<StackLayout StyleClass="box-row"
|
|
||||||
IsVisible="{Binding Cipher.Identity.Phone, Converter={StaticResource stringHasValue}}">
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n Phone}"
|
|
||||||
StyleClass="box-label" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Identity.Phone, Mode=OneWay}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
</StackLayout>
|
|
||||||
<BoxView StyleClass="box-row-separator"
|
|
||||||
IsVisible="{Binding Cipher.Identity.Phone, Converter={StaticResource stringHasValue}}" />
|
|
||||||
<StackLayout StyleClass="box-row" IsVisible="{Binding ShowIdentityAddress}">
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n Address}"
|
|
||||||
StyleClass="box-label" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Identity.Address1, Mode=OneWay}"
|
|
||||||
IsVisible="{Binding Cipher.Identity.Address1, Converter={StaticResource stringHasValue}}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Identity.Address2, Mode=OneWay}"
|
|
||||||
IsVisible="{Binding Cipher.Identity.Address2, Converter={StaticResource stringHasValue}}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Identity.Address3, Mode=OneWay}"
|
|
||||||
IsVisible="{Binding Cipher.Identity.Address3, Converter={StaticResource stringHasValue}}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Identity.FullAddressPart2, Mode=OneWay}"
|
|
||||||
IsVisible="{Binding Cipher.Identity.FullAddressPart2, Converter={StaticResource stringHasValue}}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding Cipher.Identity.Country, Mode=OneWay}"
|
|
||||||
IsVisible="{Binding Cipher.Identity.Country, Converter={StaticResource stringHasValue}}"
|
|
||||||
StyleClass="box-value" />
|
|
||||||
</StackLayout>
|
|
||||||
<BoxView StyleClass="box-row-separator" IsVisible="{Binding ShowIdentityAddress}" />
|
|
||||||
</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"
|
|
||||||
IsVisible="{Binding IsWebsite, Mode=OneWay, Converter={StaticResource inverseBool}}" />
|
|
||||||
<Label
|
|
||||||
Text="{u:I18n Website}"
|
|
||||||
StyleClass="box-label"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="0"
|
|
||||||
IsVisible="{Binding IsWebsite, Mode=OneWay}" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding HostnameOrUri, 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.LaunchUriCommand, Source={x:Reference _page}}"
|
|
||||||
CommandParameter="{Binding .}"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="1"
|
|
||||||
Grid.RowSpan="2"
|
|
||||||
IsVisible="{Binding CanLaunch, Mode=OneWay}" />
|
|
||||||
<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 Cipher.Notes, Converter={StaticResource stringHasValue}}">
|
|
||||||
<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 Cipher.HasFields}">
|
|
||||||
<StackLayout StyleClass="box-row-header">
|
|
||||||
<Label Text="{u:I18n CustomFields}"
|
|
||||||
StyleClass="box-header, box-header-platform" />
|
|
||||||
</StackLayout>
|
|
||||||
<controls:RepeaterView ItemsSource="{Binding Fields}">
|
|
||||||
<controls:RepeaterView.ItemTemplate>
|
|
||||||
<DataTemplate x:DataType="pages:AddEditPageFieldViewModel">
|
|
||||||
<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="{Binding Field.Name, Mode=OneWay}"
|
|
||||||
StyleClass="box-label"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="0" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding ValueText, Mode=OneWay}"
|
|
||||||
StyleClass="box-value"
|
|
||||||
Grid.Row="1"
|
|
||||||
Grid.Column="0"
|
|
||||||
IsVisible="{Binding IsTextType}" />
|
|
||||||
<controls:FaLabel
|
|
||||||
Text="{Binding ValueText, Mode=OneWay}"
|
|
||||||
StyleClass="box-value"
|
|
||||||
Grid.Row="1"
|
|
||||||
Grid.Column="0"
|
|
||||||
IsVisible="{Binding IsBooleanType}"
|
|
||||||
Margin="0, 5, 0, 0" />
|
|
||||||
<StackLayout IsVisible="{Binding IsHiddenType}"
|
|
||||||
Grid.Row="1"
|
|
||||||
Grid.Column="0">
|
|
||||||
<controls:MonoLabel
|
|
||||||
Text="{Binding ValueText, Mode=OneWay}"
|
|
||||||
StyleClass="box-value"
|
|
||||||
IsVisible="{Binding ShowHiddenValue}" />
|
|
||||||
<controls:MonoLabel
|
|
||||||
Text="{Binding Field.MaskedValue, Mode=OneWay}"
|
|
||||||
StyleClass="box-value"
|
|
||||||
IsVisible="{Binding ShowHiddenValue, Converter={StaticResource inverseBool}}" />
|
|
||||||
</StackLayout>
|
|
||||||
<controls:FaButton
|
|
||||||
StyleClass="box-row-button, box-row-button-platform"
|
|
||||||
Text="{Binding ShowHiddenValueIcon}"
|
|
||||||
Command="{Binding ToggleHiddenValueCommand}"
|
|
||||||
IsVisible="{Binding IsHiddenType}"
|
|
||||||
Grid.Row="0"
|
|
||||||
Grid.Column="1"
|
|
||||||
Grid.RowSpan="2" />
|
|
||||||
<controls:FaButton
|
|
||||||
StyleClass="box-row-button, box-row-button-platform"
|
|
||||||
Text=""
|
|
||||||
Command="{Binding BindingContext.CopyFieldCommand, Source={x:Reference _page}}"
|
|
||||||
CommandParameter="{Binding Field}"
|
|
||||||
IsVisible="{Binding ShowCopyButton}"
|
|
||||||
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 ShowAttachments}">
|
|
||||||
<StackLayout StyleClass="box-row-header">
|
|
||||||
<Label Text="{u:I18n Attachments}"
|
|
||||||
StyleClass="box-header, box-header-platform" />
|
|
||||||
</StackLayout>
|
|
||||||
<controls:RepeaterView ItemsSource="{Binding Cipher.Attachments}">
|
|
||||||
<controls:RepeaterView.ItemTemplate>
|
|
||||||
<DataTemplate x:DataType="views:AttachmentView">
|
|
||||||
<StackLayout Spacing="0" Padding="0">
|
|
||||||
<StackLayout Orientation="Horizontal" StyleClass="box-row" Spacing="10">
|
|
||||||
<Label
|
|
||||||
Text="{Binding FileName, Mode=OneWay}"
|
|
||||||
StyleClass="box-value"
|
|
||||||
VerticalTextAlignment="Center"
|
|
||||||
HorizontalOptions="StartAndExpand" />
|
|
||||||
<Label
|
|
||||||
Text="{Binding SizeName, Mode=OneWay}"
|
|
||||||
StyleClass="box-sub-label"
|
|
||||||
HorizontalTextAlignment="End"
|
|
||||||
VerticalTextAlignment="Center" />
|
|
||||||
<controls:FaButton
|
|
||||||
StyleClass="box-row-button, box-row-button-platform"
|
|
||||||
Text=""
|
|
||||||
Command="{Binding BindingContext.DownloadAttachmentCommand, Source={x:Reference _page}}"
|
|
||||||
CommandParameter="{Binding .}"
|
|
||||||
VerticalOptions="Center" />
|
|
||||||
</StackLayout>
|
|
||||||
<BoxView StyleClass="box-row-separator" />
|
|
||||||
</StackLayout>
|
|
||||||
</DataTemplate>
|
|
||||||
</controls:RepeaterView.ItemTemplate>
|
|
||||||
</controls:RepeaterView>
|
|
||||||
</StackLayout>
|
|
||||||
<StackLayout StyleClass="box-bottom">
|
|
||||||
<Label FormattedText="{Binding UpdatedText}"
|
|
||||||
StyleClass="box-footer-label" />
|
|
||||||
<Label FormattedText="{Binding PasswordUpdatedText}"
|
|
||||||
StyleClass="box-footer-label"
|
|
||||||
IsVisible="{Binding Cipher.PasswordRevisionDisplayDate, Converter={StaticResource notNull}}">
|
|
||||||
<Label.GestureRecognizers>
|
|
||||||
<TapGestureRecognizer Tapped="PasswordHistory_Tapped" />
|
|
||||||
</Label.GestureRecognizers>
|
|
||||||
</Label>
|
|
||||||
<Label FormattedText="{Binding PasswordHistoryText}"
|
|
||||||
StyleClass="box-footer-label"
|
|
||||||
IsVisible="{Binding Cipher.HasPasswordHistory}">
|
|
||||||
<Label.GestureRecognizers>
|
|
||||||
<TapGestureRecognizer Tapped="PasswordHistory_Tapped" />
|
|
||||||
</Label.GestureRecognizers>
|
|
||||||
</Label>
|
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
@ -1,51 +1,36 @@
|
|||||||
using Bit.Core.Abstractions;
|
using Xamarin.Forms;
|
||||||
using Bit.Core.Utilities;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Xamarin.Forms;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
public partial class AddEditPage : BaseContentPage
|
public partial class AddEditPage : BaseContentPage
|
||||||
{
|
{
|
||||||
private readonly IBroadcasterService _broadcasterService;
|
|
||||||
private AddEditPageViewModel _vm;
|
private AddEditPageViewModel _vm;
|
||||||
|
|
||||||
public AddEditPage(string cipherId)
|
public AddEditPage(
|
||||||
|
string cipherId = null,
|
||||||
|
string folderId = null,
|
||||||
|
string collectionId = null,
|
||||||
|
string organizationId = null)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
|
|
||||||
_vm = BindingContext as AddEditPageViewModel;
|
_vm = BindingContext as AddEditPageViewModel;
|
||||||
_vm.Page = this;
|
_vm.Page = this;
|
||||||
_vm.CipherId = cipherId;
|
_vm.CipherId = cipherId;
|
||||||
|
_vm.FolderId = folderId;
|
||||||
|
_vm.OrganizationId = organizationId;
|
||||||
|
_vm.Init();
|
||||||
SetActivityIndicator();
|
SetActivityIndicator();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async void OnAppearing()
|
protected override async void OnAppearing()
|
||||||
{
|
{
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
_broadcasterService.Subscribe(nameof(ViewPage), async (message) =>
|
|
||||||
{
|
|
||||||
if(message.Command == "syncCompleted")
|
|
||||||
{
|
|
||||||
var data = message.Data as Dictionary<string, object>;
|
|
||||||
if(data.ContainsKey("successfully"))
|
|
||||||
{
|
|
||||||
var success = data["successfully"] as bool?;
|
|
||||||
if(success.HasValue && success.Value)
|
|
||||||
{
|
|
||||||
await _vm.LoadAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
await LoadOnAppearedAsync(_scrollView, true, () => _vm.LoadAsync());
|
await LoadOnAppearedAsync(_scrollView, true, () => _vm.LoadAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDisappearing()
|
protected override void OnDisappearing()
|
||||||
{
|
{
|
||||||
base.OnDisappearing();
|
base.OnDisappearing();
|
||||||
_broadcasterService.Unsubscribe(nameof(ViewPage));
|
|
||||||
_vm.CleanUp();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void PasswordHistory_Tapped(object sender, System.EventArgs e)
|
private async void PasswordHistory_Tapped(object sender, System.EventArgs e)
|
||||||
@ -55,5 +40,13 @@ namespace Bit.App.Pages
|
|||||||
await Navigation.PushModalAsync(new NavigationPage(new PasswordHistoryPage(_vm.CipherId)));
|
await Navigation.PushModalAsync(new NavigationPage(new PasswordHistoryPage(_vm.CipherId)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void Save_Clicked(object sender, System.EventArgs e)
|
||||||
|
{
|
||||||
|
if(DoOnce())
|
||||||
|
{
|
||||||
|
await _vm.SubmitAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
using Bit.App.Utilities;
|
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.Models.View;
|
using Bit.Core.Models.View;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -17,49 +17,37 @@ namespace Bit.App.Pages
|
|||||||
private readonly IDeviceActionService _deviceActionService;
|
private readonly IDeviceActionService _deviceActionService;
|
||||||
private readonly ICipherService _cipherService;
|
private readonly ICipherService _cipherService;
|
||||||
private readonly IUserService _userService;
|
private readonly IUserService _userService;
|
||||||
private readonly ITotpService _totpService;
|
|
||||||
private readonly IPlatformUtilsService _platformUtilsService;
|
private readonly IPlatformUtilsService _platformUtilsService;
|
||||||
private readonly IAuditService _auditService;
|
private readonly IAuditService _auditService;
|
||||||
|
private readonly IMessagingService _messagingService;
|
||||||
private CipherView _cipher;
|
private CipherView _cipher;
|
||||||
private List<AddEditPageFieldViewModel> _fields;
|
private List<AddEditPageFieldViewModel> _fields;
|
||||||
private bool _canAccessPremium;
|
|
||||||
private bool _showPassword;
|
private bool _showPassword;
|
||||||
private bool _showCardCode;
|
private bool _showCardCode;
|
||||||
private string _totpCode;
|
|
||||||
private string _totpCodeFormatted;
|
|
||||||
private string _totpSec;
|
|
||||||
private bool _totpLow;
|
|
||||||
private DateTime? _totpInterval = null;
|
|
||||||
|
|
||||||
public AddEditPageViewModel()
|
public AddEditPageViewModel()
|
||||||
{
|
{
|
||||||
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||||
_cipherService = ServiceContainer.Resolve<ICipherService>("cipherService");
|
_cipherService = ServiceContainer.Resolve<ICipherService>("cipherService");
|
||||||
_userService = ServiceContainer.Resolve<IUserService>("userService");
|
_userService = ServiceContainer.Resolve<IUserService>("userService");
|
||||||
_totpService = ServiceContainer.Resolve<ITotpService>("totpService");
|
|
||||||
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
||||||
_auditService = ServiceContainer.Resolve<IAuditService>("auditService");
|
_auditService = ServiceContainer.Resolve<IAuditService>("auditService");
|
||||||
CopyCommand = new Command<string>((id) => CopyAsync(id, null));
|
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
||||||
CopyUriCommand = new Command<LoginUriView>(CopyUri);
|
GeneratePasswordCommand = new Command(GeneratePassword);
|
||||||
CopyFieldCommand = new Command<FieldView>(CopyField);
|
|
||||||
LaunchUriCommand = new Command<LoginUriView>(LaunchUri);
|
|
||||||
TogglePasswordCommand = new Command(TogglePassword);
|
TogglePasswordCommand = new Command(TogglePassword);
|
||||||
ToggleCardCodeCommand = new Command(ToggleCardCode);
|
ToggleCardCodeCommand = new Command(ToggleCardCode);
|
||||||
CheckPasswordCommand = new Command(CheckPasswordAsync);
|
CheckPasswordCommand = new Command(CheckPasswordAsync);
|
||||||
DownloadAttachmentCommand = new Command<AttachmentView>(DownloadAttachmentAsync);
|
|
||||||
|
|
||||||
PageTitle = AppResources.ViewItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Command CopyCommand { get; set; }
|
public Command GeneratePasswordCommand { get; set; }
|
||||||
public Command CopyUriCommand { get; set; }
|
|
||||||
public Command CopyFieldCommand { get; set; }
|
|
||||||
public Command LaunchUriCommand { get; set; }
|
|
||||||
public Command TogglePasswordCommand { get; set; }
|
public Command TogglePasswordCommand { get; set; }
|
||||||
public Command ToggleCardCodeCommand { get; set; }
|
public Command ToggleCardCodeCommand { get; set; }
|
||||||
public Command CheckPasswordCommand { get; set; }
|
public Command CheckPasswordCommand { get; set; }
|
||||||
public Command DownloadAttachmentCommand { get; set; }
|
|
||||||
public string CipherId { get; set; }
|
public string CipherId { get; set; }
|
||||||
|
public string OrganizationId { get; set; }
|
||||||
|
public string FolderId { get; set; }
|
||||||
|
public CipherType? Type { get; set; }
|
||||||
|
public List<string> CollectionIds { get; set; }
|
||||||
public CipherView Cipher
|
public CipherView Cipher
|
||||||
{
|
{
|
||||||
get => _cipher;
|
get => _cipher;
|
||||||
@ -72,11 +60,6 @@ namespace Bit.App.Pages
|
|||||||
nameof(IsSecureNote),
|
nameof(IsSecureNote),
|
||||||
nameof(ShowUris),
|
nameof(ShowUris),
|
||||||
nameof(ShowAttachments),
|
nameof(ShowAttachments),
|
||||||
nameof(ShowTotp),
|
|
||||||
nameof(ColoredPassword),
|
|
||||||
nameof(UpdatedText),
|
|
||||||
nameof(PasswordUpdatedText),
|
|
||||||
nameof(PasswordHistoryText),
|
|
||||||
nameof(ShowIdentityAddress),
|
nameof(ShowIdentityAddress),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -85,11 +68,6 @@ namespace Bit.App.Pages
|
|||||||
get => _fields;
|
get => _fields;
|
||||||
set => SetProperty(ref _fields, value);
|
set => SetProperty(ref _fields, value);
|
||||||
}
|
}
|
||||||
public bool CanAccessPremium
|
|
||||||
{
|
|
||||||
get => _canAccessPremium;
|
|
||||||
set => SetProperty(ref _canAccessPremium, value);
|
|
||||||
}
|
|
||||||
public bool ShowPassword
|
public bool ShowPassword
|
||||||
{
|
{
|
||||||
get => _showPassword;
|
get => _showPassword;
|
||||||
@ -108,131 +86,124 @@ namespace Bit.App.Pages
|
|||||||
nameof(ShowCardCodeIcon)
|
nameof(ShowCardCodeIcon)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public bool IsLogin => Cipher?.Type == Core.Enums.CipherType.Login;
|
public bool EditMode => !string.IsNullOrWhiteSpace(CipherId);
|
||||||
public bool IsIdentity => Cipher?.Type == Core.Enums.CipherType.Identity;
|
public bool IsLogin => Cipher?.Type == CipherType.Login;
|
||||||
public bool IsCard => Cipher?.Type == Core.Enums.CipherType.Card;
|
public bool IsIdentity => Cipher?.Type == CipherType.Identity;
|
||||||
public bool IsSecureNote => Cipher?.Type == Core.Enums.CipherType.SecureNote;
|
public bool IsCard => Cipher?.Type == CipherType.Card;
|
||||||
public FormattedString ColoredPassword => PasswordFormatter.FormatPassword(Cipher.Login.Password);
|
public bool IsSecureNote => Cipher?.Type == CipherType.SecureNote;
|
||||||
public FormattedString UpdatedText
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var fs = new FormattedString();
|
|
||||||
fs.Spans.Add(new Span
|
|
||||||
{
|
|
||||||
Text = string.Format("{0}:", AppResources.DateUpdated),
|
|
||||||
FontAttributes = FontAttributes.Bold
|
|
||||||
});
|
|
||||||
fs.Spans.Add(new Span
|
|
||||||
{
|
|
||||||
Text = string.Format(" {0} {1}",
|
|
||||||
Cipher.RevisionDate.ToShortDateString(),
|
|
||||||
Cipher.RevisionDate.ToShortTimeString())
|
|
||||||
});
|
|
||||||
return fs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public FormattedString PasswordUpdatedText
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var fs = new FormattedString();
|
|
||||||
fs.Spans.Add(new Span
|
|
||||||
{
|
|
||||||
Text = string.Format("{0}:", AppResources.DatePasswordUpdated),
|
|
||||||
FontAttributes = FontAttributes.Bold
|
|
||||||
});
|
|
||||||
fs.Spans.Add(new Span
|
|
||||||
{
|
|
||||||
Text = string.Format(" {0} {1}",
|
|
||||||
Cipher.PasswordRevisionDisplayDate?.ToShortDateString(),
|
|
||||||
Cipher.PasswordRevisionDisplayDate?.ToShortTimeString())
|
|
||||||
});
|
|
||||||
return fs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public FormattedString PasswordHistoryText
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var fs = new FormattedString();
|
|
||||||
fs.Spans.Add(new Span
|
|
||||||
{
|
|
||||||
Text = string.Format("{0}:", AppResources.PasswordHistory),
|
|
||||||
FontAttributes = FontAttributes.Bold
|
|
||||||
});
|
|
||||||
fs.Spans.Add(new Span
|
|
||||||
{
|
|
||||||
Text = string.Format(" {0}", Cipher.PasswordHistory.Count.ToString()),
|
|
||||||
TextColor = (Color)Application.Current.Resources["PrimaryColor"]
|
|
||||||
});
|
|
||||||
return fs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public bool ShowUris => IsLogin && Cipher.Login.HasUris;
|
public bool ShowUris => IsLogin && Cipher.Login.HasUris;
|
||||||
public bool ShowIdentityAddress => IsIdentity && (
|
public bool ShowIdentityAddress => IsIdentity && (
|
||||||
!string.IsNullOrWhiteSpace(Cipher.Identity.Address1) ||
|
!string.IsNullOrWhiteSpace(Cipher.Identity.Address1) ||
|
||||||
!string.IsNullOrWhiteSpace(Cipher.Identity.City) ||
|
!string.IsNullOrWhiteSpace(Cipher.Identity.City) ||
|
||||||
!string.IsNullOrWhiteSpace(Cipher.Identity.Country));
|
!string.IsNullOrWhiteSpace(Cipher.Identity.Country));
|
||||||
public bool ShowAttachments => Cipher.HasAttachments && (CanAccessPremium || Cipher.OrganizationId != null);
|
public bool ShowAttachments => Cipher.HasAttachments;
|
||||||
public bool ShowTotp => IsLogin && !string.IsNullOrWhiteSpace(Cipher.Login.Totp) &&
|
|
||||||
!string.IsNullOrWhiteSpace(TotpCodeFormatted);
|
|
||||||
public string ShowPasswordIcon => ShowPassword ? "" : "";
|
public string ShowPasswordIcon => ShowPassword ? "" : "";
|
||||||
public string ShowCardCodeIcon => ShowCardCode ? "" : "";
|
public string ShowCardCodeIcon => ShowCardCode ? "" : "";
|
||||||
public string TotpCodeFormatted
|
|
||||||
|
public void Init()
|
||||||
{
|
{
|
||||||
get => _totpCodeFormatted;
|
PageTitle = EditMode ? AppResources.EditItem : AppResources.AddItem;
|
||||||
set => SetProperty(ref _totpCodeFormatted, value,
|
|
||||||
additionalPropertyNames: new string[]
|
|
||||||
{
|
|
||||||
nameof(ShowTotp)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
public string TotpSec
|
|
||||||
{
|
|
||||||
get => _totpSec;
|
|
||||||
set => SetProperty(ref _totpSec, value);
|
|
||||||
}
|
|
||||||
public bool TotpLow
|
|
||||||
{
|
|
||||||
get => _totpLow;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _totpLow, value);
|
|
||||||
Page.Resources["textTotp"] = Application.Current.Resources[value ? "text-danger" : "text-default"];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task LoadAsync()
|
public async Task LoadAsync()
|
||||||
{
|
{
|
||||||
CleanUp();
|
// TODO: load collections
|
||||||
|
|
||||||
|
if(EditMode)
|
||||||
|
{
|
||||||
var cipher = await _cipherService.GetAsync(CipherId);
|
var cipher = await _cipherService.GetAsync(CipherId);
|
||||||
Cipher = await cipher.DecryptAsync();
|
Cipher = await cipher.DecryptAsync();
|
||||||
CanAccessPremium = await _userService.CanAccessPremiumAsync();
|
|
||||||
Fields = Cipher.Fields?.Select(f => new AddEditPageFieldViewModel(f)).ToList();
|
Fields = Cipher.Fields?.Select(f => new AddEditPageFieldViewModel(f)).ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Cipher = new CipherView
|
||||||
|
{
|
||||||
|
OrganizationId = OrganizationId,
|
||||||
|
FolderId = FolderId,
|
||||||
|
Type = Type.GetValueOrDefault(CipherType.Login),
|
||||||
|
Login = new LoginView(),
|
||||||
|
Card = new CardView(),
|
||||||
|
Identity = new IdentityView(),
|
||||||
|
SecureNote = new SecureNoteView()
|
||||||
|
};
|
||||||
|
Cipher.Login.Uris = new List<LoginUriView>();
|
||||||
|
Cipher.SecureNote.Type = SecureNoteType.Generic;
|
||||||
|
|
||||||
if(Cipher.Type == Core.Enums.CipherType.Login && !string.IsNullOrWhiteSpace(Cipher.Login.Totp) &&
|
// TODO: org/collection stuff
|
||||||
(Cipher.OrganizationUseTotp || CanAccessPremium))
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> SubmitAsync()
|
||||||
{
|
{
|
||||||
await TotpUpdateCodeAsync();
|
if(string.IsNullOrWhiteSpace(Cipher.Name))
|
||||||
var interval = _totpService.GetTimeInterval(Cipher.Login.Totp);
|
|
||||||
await TotpTickAsync(interval);
|
|
||||||
_totpInterval = DateTime.UtcNow;
|
|
||||||
Device.StartTimer(new TimeSpan(0, 0, 1), () =>
|
|
||||||
{
|
{
|
||||||
if(_totpInterval == null)
|
await Page.DisplayAlert(AppResources.AnErrorHasOccurred,
|
||||||
|
string.Format(AppResources.ValidationFieldRequired, AppResources.Name),
|
||||||
|
AppResources.Ok);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!EditMode && Cipher.Type == CipherType.Login && (Cipher.Login.Uris?.Count ?? 0) == 1 &&
|
||||||
|
string.IsNullOrWhiteSpace(Cipher.Login.Uris.First().Uri))
|
||||||
|
{
|
||||||
|
Cipher.Login.Uris = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!EditMode && Cipher.OrganizationId != null)
|
||||||
|
{
|
||||||
|
// TODO: filter cipher collection ids
|
||||||
|
}
|
||||||
|
|
||||||
|
var cipher = await _cipherService.EncryptAsync(Cipher);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _deviceActionService.ShowLoadingAsync(AppResources.Saving);
|
||||||
|
await _cipherService.SaveWithServerAsync(cipher);
|
||||||
|
Cipher.Id = cipher.Id;
|
||||||
|
await _deviceActionService.HideLoadingAsync();
|
||||||
|
_platformUtilsService.ShowToast("success", null,
|
||||||
|
EditMode ? AppResources.ItemUpdated : AppResources.NewItemCreated);
|
||||||
|
_messagingService.Send(EditMode ? "editedCipher" : "addedCipher");
|
||||||
|
await Page.Navigation.PopModalAsync();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch(ApiException e)
|
||||||
|
{
|
||||||
|
await _deviceActionService.HideLoadingAsync();
|
||||||
|
await Page.DisplayAlert(AppResources.AnErrorHasOccurred, e.Error.GetSingleMessage(), AppResources.Ok);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> DeleteAsync()
|
||||||
|
{
|
||||||
|
var confirmed = await _platformUtilsService.ShowDialogAsync(AppResources.DoYouReallyWantToDelete,
|
||||||
|
null, AppResources.Yes, AppResources.No);
|
||||||
|
if(!confirmed)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var task = TotpTickAsync(interval);
|
try
|
||||||
|
{
|
||||||
|
await _deviceActionService.ShowLoadingAsync(AppResources.Deleting);
|
||||||
|
await _cipherService.DeleteWithServerAsync(Cipher.Id);
|
||||||
|
await _deviceActionService.HideLoadingAsync();
|
||||||
|
_platformUtilsService.ShowToast("success", null, AppResources.ItemDeleted);
|
||||||
|
_messagingService.Send("deletedCipher");
|
||||||
return true;
|
return true;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
catch(ApiException e)
|
||||||
|
{
|
||||||
|
await _deviceActionService.HideLoadingAsync();
|
||||||
|
await Page.DisplayAlert(AppResources.AnErrorHasOccurred, e.Error.GetSingleMessage(), AppResources.Ok);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CleanUp()
|
public void GeneratePassword()
|
||||||
{
|
{
|
||||||
_totpInterval = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TogglePassword()
|
public void TogglePassword()
|
||||||
@ -245,47 +216,6 @@ namespace Bit.App.Pages
|
|||||||
ShowCardCode = !ShowCardCode;
|
ShowCardCode = !ShowCardCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task TotpUpdateCodeAsync()
|
|
||||||
{
|
|
||||||
if(Cipher == null || Cipher.Type != Core.Enums.CipherType.Login || Cipher.Login.Totp == null)
|
|
||||||
{
|
|
||||||
_totpInterval = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_totpCode = await _totpService.GetCodeAsync(Cipher.Login.Totp);
|
|
||||||
if(_totpCode != null)
|
|
||||||
{
|
|
||||||
if(_totpCode.Length > 4)
|
|
||||||
{
|
|
||||||
var half = (int)Math.Floor(_totpCode.Length / 2M);
|
|
||||||
TotpCodeFormatted = string.Format("{0} {1}", _totpCode.Substring(0, half),
|
|
||||||
_totpCode.Substring(half));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TotpCodeFormatted = _totpCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TotpCodeFormatted = null;
|
|
||||||
_totpInterval = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task TotpTickAsync(int intervalSeconds)
|
|
||||||
{
|
|
||||||
var epoc = CoreHelpers.EpocUtcNow() / 1000;
|
|
||||||
var mod = epoc % intervalSeconds;
|
|
||||||
var totpSec = intervalSeconds - mod;
|
|
||||||
TotpSec = totpSec.ToString();
|
|
||||||
TotpLow = totpSec < 7;
|
|
||||||
if(mod == 0)
|
|
||||||
{
|
|
||||||
await TotpUpdateCodeAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void CheckPasswordAsync()
|
private async void CheckPasswordAsync()
|
||||||
{
|
{
|
||||||
if(!(Page as BaseContentPage).DoOnce())
|
if(!(Page as BaseContentPage).DoOnce())
|
||||||
@ -309,120 +239,6 @@ namespace Bit.App.Pages
|
|||||||
await _platformUtilsService.ShowDialogAsync(AppResources.PasswordSafe);
|
await _platformUtilsService.ShowDialogAsync(AppResources.PasswordSafe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void DownloadAttachmentAsync(AttachmentView attachment)
|
|
||||||
{
|
|
||||||
if(!(Page as BaseContentPage).DoOnce())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(Cipher.OrganizationId == null && !CanAccessPremium)
|
|
||||||
{
|
|
||||||
await _platformUtilsService.ShowDialogAsync(AppResources.PremiumRequired);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(attachment.FileSize >= 10485760) // 10 MB
|
|
||||||
{
|
|
||||||
var confirmed = await _platformUtilsService.ShowDialogAsync(
|
|
||||||
string.Format(AppResources.AttachmentLargeWarning, attachment.SizeName), null,
|
|
||||||
AppResources.Yes, AppResources.No);
|
|
||||||
if(!confirmed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!_deviceActionService.CanOpenFile(attachment.FileName))
|
|
||||||
{
|
|
||||||
await _platformUtilsService.ShowDialogAsync(AppResources.UnableToOpenFile);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await _deviceActionService.ShowLoadingAsync(AppResources.Downloading);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var data = await _cipherService.DownloadAndDecryptAttachmentAsync(attachment, Cipher.OrganizationId);
|
|
||||||
await _deviceActionService.HideLoadingAsync();
|
|
||||||
if(data == null)
|
|
||||||
{
|
|
||||||
await _platformUtilsService.ShowDialogAsync(AppResources.UnableToDownloadFile);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(!_deviceActionService.OpenFile(data, attachment.Id, attachment.FileName))
|
|
||||||
{
|
|
||||||
await _platformUtilsService.ShowDialogAsync(AppResources.UnableToOpenFile);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await _deviceActionService.HideLoadingAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void CopyAsync(string id, string text = null)
|
|
||||||
{
|
|
||||||
string name = null;
|
|
||||||
if(id == "LoginUsername")
|
|
||||||
{
|
|
||||||
text = Cipher.Login.Username;
|
|
||||||
name = AppResources.Username;
|
|
||||||
}
|
|
||||||
else if(id == "LoginPassword")
|
|
||||||
{
|
|
||||||
text = Cipher.Login.Password;
|
|
||||||
name = AppResources.Password;
|
|
||||||
}
|
|
||||||
else if(id == "LoginTotp")
|
|
||||||
{
|
|
||||||
text = _totpCode;
|
|
||||||
name = AppResources.VerificationCodeTotp;
|
|
||||||
}
|
|
||||||
else if(id == "LoginUri")
|
|
||||||
{
|
|
||||||
name = AppResources.URI;
|
|
||||||
}
|
|
||||||
else if(id == "FieldValue")
|
|
||||||
{
|
|
||||||
name = AppResources.Value;
|
|
||||||
}
|
|
||||||
else if(id == "CardNumber")
|
|
||||||
{
|
|
||||||
text = Cipher.Card.Number;
|
|
||||||
name = AppResources.Number;
|
|
||||||
}
|
|
||||||
else if(id == "CardCode")
|
|
||||||
{
|
|
||||||
text = Cipher.Card.Code;
|
|
||||||
name = AppResources.SecurityCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(text != null)
|
|
||||||
{
|
|
||||||
await _platformUtilsService.CopyToClipboardAsync(text);
|
|
||||||
if(!string.IsNullOrWhiteSpace(name))
|
|
||||||
{
|
|
||||||
_platformUtilsService.ShowToast("info", null, string.Format(AppResources.ValueHasBeenCopied, name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CopyUri(LoginUriView uri)
|
|
||||||
{
|
|
||||||
CopyAsync("LoginUri", uri.Uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CopyField(FieldView field)
|
|
||||||
{
|
|
||||||
CopyAsync("FieldValue", field.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LaunchUri(LoginUriView uri)
|
|
||||||
{
|
|
||||||
if(uri.CanLaunch && (Page as BaseContentPage).DoOnce())
|
|
||||||
{
|
|
||||||
_platformUtilsService.LaunchUri(uri.LaunchUri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AddEditPageFieldViewModel : BaseViewModel
|
public class AddEditPageFieldViewModel : BaseViewModel
|
||||||
|
Loading…
Reference in New Issue
Block a user