WIP strings in ressource file (XAML is done, code-behind is not)

Invalid URI now shows a message
Create entry is now a link above entries
Entries gridview allows reordering (WIP enable it conditionnally)
Code cleanup in adding/removing PwEntries from VM
This commit is contained in:
BONNEVILLE Geoffroy
2017-11-28 18:53:10 +01:00
parent fcbda1e33d
commit 7b39fe79c8
17 changed files with 587 additions and 233 deletions

View File

@@ -34,7 +34,7 @@
<RowDefinition Height="*" /> <RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<CheckBox Grid.Row="0" Grid.Column="0" IsChecked="{Binding HasPassword, Mode=TwoWay}" /> <CheckBox Grid.Row="0" Grid.Column="0" IsChecked="{Binding HasPassword, Mode=TwoWay}" />
<PasswordBox Grid.Row="0" Grid.Column="1" x:Name="PasswordBox" Password="{Binding Password, Mode=TwoWay}" Height="30" IsEnabled="{Binding HasPassword}" IsPasswordRevealButtonEnabled="True" KeyDown="PasswordBox_KeyDown" PlaceholderText="Password" BorderBrush="{Binding StatusType, Converter={StaticResource DiscreteIntToSolidColorBrushConverter}}" > <PasswordBox Grid.Row="0" Grid.Column="1" x:Name="PasswordBox" x:Uid="CompositeKeyPassword" Password="{Binding Password, Mode=TwoWay}" Height="30" IsEnabled="{Binding HasPassword}" IsPasswordRevealButtonEnabled="True" KeyDown="PasswordBox_KeyDown" BorderBrush="{Binding StatusType, Converter={StaticResource DiscreteIntToSolidColorBrushConverter}}" >
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding HasPassword}" Value="True"> <core:DataTriggerBehavior Binding="{Binding HasPassword}" Value="True">
<actions:SetupFocusAction TargetObject="{Binding ElementName=PasswordBox}" /> <actions:SetupFocusAction TargetObject="{Binding ElementName=PasswordBox}" />
@@ -51,7 +51,7 @@
<HyperlinkButton Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" Visibility="{Binding ShowComplexityIndicator, ElementName=UserControl, Converter={StaticResource BooleanToVisibilityConverter}}" IsEnabled="{Binding HasKeyFile}" Click="CreateKeyFileButton_Click"> <HyperlinkButton Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" Visibility="{Binding ShowComplexityIndicator, ElementName=UserControl, Converter={StaticResource BooleanToVisibilityConverter}}" IsEnabled="{Binding HasKeyFile}" Click="CreateKeyFileButton_Click">
<SymbolIcon Symbol="Add"> <SymbolIcon Symbol="Add">
<ToolTipService.ToolTip> <ToolTipService.ToolTip>
<ToolTip Content="Create new key file" /> <ToolTip x:Uid="CompositeKeyNewKeyFileTooltip" />
</ToolTipService.ToolTip> </ToolTipService.ToolTip>
</SymbolIcon> </SymbolIcon>
</HyperlinkButton> </HyperlinkButton>

View File

@@ -210,6 +210,7 @@
<None Include="packages.config"> <None Include="packages.config">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</None> </None>
<PRIResource Include="Strings\en-US\Resources.resw" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Package.StoreAssociation.xml" /> <None Include="Package.StoreAssociation.xml" />

View File

@@ -337,21 +337,21 @@
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
<StackPanel> <StackPanel>
<TextBlock> <TextBlock>
<Run Text="Password Length: "/> <Run x:Uid="PasswordGeneratorLength" />
<Run Text="{Binding PasswordLength}" /> <Run Text="{Binding PasswordLength}" />
</TextBlock> </TextBlock>
<Slider Value="{Binding PasswordLength, Mode=TwoWay}" Margin="0,-10,0,-20" /> <Slider Value="{Binding PasswordLength, Mode=TwoWay}" Margin="0,-10,0,-20" />
<CheckBox IsChecked="{Binding UpperCasePatternSelected, Mode=TwoWay}" Content="Upper case (A, B, C, ...)"/> <CheckBox IsChecked="{Binding UpperCasePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorUpper" />
<CheckBox IsChecked="{Binding LowerCasePatternSelected, Mode=TwoWay}" Content="Lower case (a, b, c, ...)"/> <CheckBox IsChecked="{Binding LowerCasePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorLower" />
<CheckBox IsChecked="{Binding DigitsPatternSelected, Mode=TwoWay}" Content="Digits (0, 1, 2, ...)"/> <CheckBox IsChecked="{Binding DigitsPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorDigits" />
<CheckBox IsChecked="{Binding MinusPatternSelected, Mode=TwoWay}" Content="Minus (-)"/> <CheckBox IsChecked="{Binding MinusPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorMinus" />
<CheckBox IsChecked="{Binding UnderscorePatternSelected, Mode=TwoWay}" Content="Underscore (_)"/> <CheckBox IsChecked="{Binding UnderscorePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorUnderscore" />
<CheckBox IsChecked="{Binding SpacePatternSelected, Mode=TwoWay}" Content="Space ( )"/> <CheckBox IsChecked="{Binding SpacePatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorSpace" />
<CheckBox IsChecked="{Binding SpecialPatternSelected, Mode=TwoWay}" Content="Special (!, $, %, ...)"/> <CheckBox IsChecked="{Binding SpecialPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorSpecial" />
<CheckBox IsChecked="{Binding BracketsPatternSelected, Mode=TwoWay}" Content="Brackets ([], {}, (), ...)"/> <CheckBox IsChecked="{Binding BracketsPatternSelected, Mode=TwoWay}" x:Uid="PasswordGeneratorBrackets" />
<TextBlock Text="Also add these characters:" Margin="0,5,0,0"/> <TextBlock x:Uid="PasswordGeneratorAlso" Margin="0,5,0,0"/>
<TextBox Text="{Binding CustomChars, Mode=TwoWay}" /> <TextBox Text="{Binding CustomChars, Mode=TwoWay}" />
<Button Content="Generate"> <Button x:Uid="PasswordGeneratorButton">
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click"> <core:EventTriggerBehavior EventName="Click">
<core:CallMethodAction TargetObject="{Binding}" MethodName="GeneratePassword"/> <core:CallMethodAction TargetObject="{Binding}" MethodName="GeneratePassword"/>
@@ -361,6 +361,9 @@
</StackPanel> </StackPanel>
</Flyout> </Flyout>
</Button.Flyout> </Button.Flyout>
<ToolTipService.ToolTip>
<ToolTip x:Uid="PasswordGeneratorTooltip" />
</ToolTipService.ToolTip>
</Button> </Button>
</Grid> </Grid>
</ControlTemplate> </ControlTemplate>
@@ -427,7 +430,7 @@
<Setter Property="Margin" Value="0,20,0,0"/> <Setter Property="Margin" Value="0,20,0,0"/>
</Style> </Style>
</StackPanel.Resources> </StackPanel.Resources>
<TextBlock TextWrapping="Wrap" Text="User name or login" FontSize="18"/> <TextBlock x:Uid="EntryLogin" TextWrapping="Wrap" FontSize="18"/>
<local:TextBoxWithButton HorizontalAlignment="Left" Text="{Binding UserName, Mode=TwoWay}" Width="350" Height="32" Style="{StaticResource TextBoxWithButtonStyle}" ButtonSymbol="&#xE16F;" ButtonTooltip="Copy"> <local:TextBoxWithButton HorizontalAlignment="Left" Text="{Binding UserName, Mode=TwoWay}" Width="350" Height="32" Style="{StaticResource TextBoxWithButtonStyle}" ButtonSymbol="&#xE16F;" ButtonTooltip="Copy">
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick"> <core:EventTriggerBehavior EventName="ButtonClick">
@@ -435,7 +438,7 @@
</core:EventTriggerBehavior> </core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</local:TextBoxWithButton> </local:TextBoxWithButton>
<TextBlock TextWrapping="Wrap" Text="Password" FontSize="18"/> <TextBlock x:Uid="EntryPassword" TextWrapping="Wrap" FontSize="18"/>
<PasswordBox HorizontalAlignment="Left" Password="{Binding Password, Mode=TwoWay}" Width="350" Height="32" IsPasswordRevealButtonEnabled="True" Visibility="{Binding IsRevealPassword, Converter={StaticResource InverseBooleanToVisibilityConverter}}" Style="{StaticResource PasswordBoxWithButtonStyle}" /> <PasswordBox HorizontalAlignment="Left" Password="{Binding Password, Mode=TwoWay}" Width="350" Height="32" IsPasswordRevealButtonEnabled="True" Visibility="{Binding IsRevealPassword, Converter={StaticResource InverseBooleanToVisibilityConverter}}" Style="{StaticResource PasswordBoxWithButtonStyle}" />
<local:TextBoxWithButton HorizontalAlignment="Left" Text="{Binding Password, Mode=TwoWay}" Width="350" Height="32" Visibility="{Binding IsRevealPassword, Converter={StaticResource BooleanToVisibilityConverter}}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonSymbol="&#xE16F;" ButtonTooltip="Copy"> <local:TextBoxWithButton HorizontalAlignment="Left" Text="{Binding Password, Mode=TwoWay}" Width="350" Height="32" Visibility="{Binding IsRevealPassword, Converter={StaticResource BooleanToVisibilityConverter}}" Style="{StaticResource TextBoxWithButtonStyle}" ButtonSymbol="&#xE16F;" ButtonTooltip="Copy">
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
@@ -445,16 +448,16 @@
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</local:TextBoxWithButton> </local:TextBoxWithButton>
<ProgressBar Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}" Maximum="128" Width="350" HorizontalAlignment="Left" Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroungBrushComplexityConverter}}" /> <ProgressBar Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}" Maximum="128" Width="350" HorizontalAlignment="Left" Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroungBrushComplexityConverter}}" />
<CheckBox HorizontalAlignment="Left" Margin="-3,0,0,0" Content="Show password" IsChecked="{Binding IsRevealPassword, Mode=TwoWay}" IsEnabled="{Binding IsRevealPasswordEnabled}" /> <CheckBox x:Uid="EntryShowPassword" HorizontalAlignment="Left" Margin="-3,0,0,0" IsChecked="{Binding IsRevealPassword, Mode=TwoWay}" IsEnabled="{Binding IsRevealPasswordEnabled}" />
<TextBlock TextWrapping="Wrap" Text="URL" FontSize="18"/> <TextBlock TextWrapping="Wrap" Text="URL" FontSize="18"/>
<local:TextBoxWithButton x:Name="UrlTextBox" HorizontalAlignment="Left" Text="{Binding Url, Mode=TwoWay}" Height="32" Width="350" MaxLength="256" Style="{StaticResource TextBoxWithButtonStyle}" ButtonClick="UrlButton_Click" ButtonSymbol="&#xE111;" ButtonTooltip="Navigate to URL" /> <local:TextBoxWithButton x:Name="UrlTextBox" HorizontalAlignment="Left" Text="{Binding Url, Mode=TwoWay}" Height="32" Width="350" MaxLength="256" Style="{StaticResource TextBoxWithButtonStyle}" ButtonClick="UrlButton_Click" ButtonSymbol="&#xE111;" ButtonTooltip="Navigate to URL" />
<TextBlock TextWrapping="Wrap" Text="Notes" FontSize="18"/> <TextBlock x:Uid="EntryNotes" TextWrapping="Wrap" FontSize="18"/>
<TextBox HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding Notes, Mode=TwoWay}" Width="350" Height="200" AcceptsReturn="True" IsSpellCheckEnabled="True" /> <TextBox HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding Notes, Mode=TwoWay}" Width="350" Height="200" AcceptsReturn="True" IsSpellCheckEnabled="True" />
<CheckBox FontSize="18" IsChecked="{Binding HasExpirationDate, Mode=TwoWay}" Content="Expiration date"/> <CheckBox x:Uid="EntryExpirationDate" FontSize="18" IsChecked="{Binding HasExpirationDate, Mode=TwoWay}" />
<StackPanel Orientation="Horizontal" IsHitTestVisible="{Binding HasExpirationDate}"> <StackPanel Orientation="Horizontal" Visibility="{Binding HasExpirationDate, Converter={StaticResource BooleanToVisibilityConverter}}">
<SymbolIcon Symbol="Important" Foreground="DarkRed" Visibility="{Binding HasExpired, Converter={StaticResource BooleanToVisibilityConverter}}"> <SymbolIcon Symbol="Important" Foreground="DarkRed" Visibility="{Binding HasExpired, Converter={StaticResource BooleanToVisibilityConverter}}">
<ToolTipService.ToolTip> <ToolTipService.ToolTip>
<ToolTip Content="Password has expired" /> <ToolTip x:Uid="EntryExpirationTooltip" />
</ToolTipService.ToolTip> </ToolTipService.ToolTip>
</SymbolIcon> </SymbolIcon>
<DatePicker Margin="0,0,20,0" Date="{Binding ExpiryDate, Mode=TwoWay}" /> <DatePicker Margin="0,0,20,0" Date="{Binding ExpiryDate, Mode=TwoWay}" />

View File

@@ -97,9 +97,9 @@ namespace ModernKeePass.Pages
var uri = new Uri(UrlTextBox.Text); var uri = new Uri(UrlTextBox.Text);
await Windows.System.Launcher.LaunchUriAsync(uri); await Windows.System.Launcher.LaunchUriAsync(uri);
} }
catch catch (Exception ex)
{ {
// TODO: Show some error MessageDialogHelper.ShowErrorDialog(ex);
} }
} }
} }

View File

@@ -18,6 +18,7 @@
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/> <converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
<converters:BooleanToFontStyleConverter x:Key="BooleanToFontStyleConverter"/> <converters:BooleanToFontStyleConverter x:Key="BooleanToFontStyleConverter"/>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/> <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
<converters:NullToBooleanConverter x:Key="NullToBooleanConverter"/> <converters:NullToBooleanConverter x:Key="NullToBooleanConverter"/>
</Page.Resources> </Page.Resources>
<Page.DataContext> <Page.DataContext>
@@ -42,6 +43,13 @@
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
</AppBarButton> </AppBarButton>
</CommandBar.SecondaryCommands> </CommandBar.SecondaryCommands>
<AppBarButton Icon="Sort" Label="Sort" Visibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<core:CallMethodAction MethodName="SortEntries" TargetObject="{Binding}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</AppBarButton>
<AppBarToggleButton Icon="Edit" Label="Edit" IsChecked="{Binding IsEditMode, Mode=TwoWay}"> <AppBarToggleButton Icon="Edit" Label="Edit" IsChecked="{Binding IsEditMode, Mode=TwoWay}">
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click"> <core:EventTriggerBehavior EventName="Click">
@@ -144,7 +152,13 @@
</ListView.HeaderTemplate> </ListView.HeaderTemplate>
</ListView> </ListView>
<!-- Horizontal scrolling grid --> <!-- Horizontal scrolling grid -->
<SemanticZoom Grid.Column="1" ViewChangeStarted="SemanticZoom_ViewChangeStarted" Margin="0,30,0,0"> <HyperlinkButton Grid.Column="1" VerticalAlignment="Top" Margin="40,0,0,0" Click="CreateEntry_ButtonClick" Visibility="{Binding IsSelected, Converter={StaticResource InverseBooleanToVisibilityConverter}}" >
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="Add"></SymbolIcon>
<TextBlock x:Uid="GroupCreateEntry" VerticalAlignment="Center" Margin="10,0,0,0" />
</StackPanel>
</HyperlinkButton>
<SemanticZoom Grid.Column="1" ViewChangeStarted="SemanticZoom_ViewChangeStarted" Margin="0,45,0,0">
<SemanticZoom.ZoomedInView> <SemanticZoom.ZoomedInView>
<GridView <GridView
x:Name="GridView" x:Name="GridView"
@@ -152,13 +166,43 @@
AutomationProperties.Name="Entries" AutomationProperties.Name="Entries"
TabIndex="1" TabIndex="1"
SelectionChanged="entries_SelectionChanged" SelectionChanged="entries_SelectionChanged"
IsSynchronizedWithCurrentItem="False"> IsSynchronizedWithCurrentItem="False"
AllowDrop="{Binding IsEditMode}"
CanReorderItems="{Binding IsEditMode}"
CanDragItems="{Binding IsEditMode}">
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="False"> <core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="False">
<actions:SetupFocusAction TargetObject="{Binding ElementName=GridView}" /> <actions:SetupFocusAction TargetObject="{Binding ElementName=GridView}" />
</core:DataTriggerBehavior> </core:DataTriggerBehavior>
</interactivity:Interaction.Behaviors> </interactivity:Interaction.Behaviors>
<GridView.Resources> <GridView.ItemTemplate>
<DataTemplate>
<Grid Height="110" Width="480" x:Name="EntryGrid" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border
Grid.Column="0"
BorderThickness="2"
BorderBrush="{StaticResource SystemColor}"
Background="{Binding BackgroundColor, ConverterParameter={StaticResource Transparent}, Converter={StaticResource ColorToBrushConverter}}">
<SymbolIcon Symbol="{Binding IconSymbol}" Width="100" Height="100" RenderTransformOrigin="0.5,0.5" >
<SymbolIcon.RenderTransform>
<CompositeTransform ScaleX="2" TranslateX="0" TranslateY="0" ScaleY="2"/>
</SymbolIcon.RenderTransform>
</SymbolIcon>
</Border>
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,10,0,0" >
<TextBlock x:Name="NameTextBlock" Text="{Binding Name}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" Foreground="{Binding ForegroundColor, ConverterParameter={StaticResource TextBoxForegroundThemeBrush}, Converter={StaticResource ColorToBrushConverter}}"/>
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
<TextBlock Text="{Binding UserName}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
<TextBlock Text="{Binding Url}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
</StackPanel>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<!--<GridView.Resources>
<DataTemplate x:Name="GroupFirstItem"> <DataTemplate x:Name="GroupFirstItem">
<Border <Border
BorderThickness="2" BorderThickness="2"
@@ -203,18 +247,18 @@
</StackPanel> </StackPanel>
</Grid> </Grid>
</DataTemplate> </DataTemplate>
</GridView.Resources> </GridView.Resources>-->
<GridView.ItemsSource> <GridView.ItemsSource>
<Binding Source="{StaticResource EntriesViewSource}"/> <Binding Source="{StaticResource EntriesViewSource}"/>
</GridView.ItemsSource> </GridView.ItemsSource>
<GridView.DataContext> <GridView.DataContext>
<viewModels:EntryVm/> <viewModels:EntryVm/>
</GridView.DataContext> </GridView.DataContext>
<GridView.ItemTemplateSelector> <!--<GridView.ItemTemplateSelector>
<templateSelectors:FirstItemDataTemplateSelector <templateSelectors:FirstItemDataTemplateSelector
FirstItem="{StaticResource GroupFirstItem}" FirstItem="{StaticResource GroupFirstItem}"
OtherItem="{StaticResource GroupOtherItem}" /> OtherItem="{StaticResource GroupOtherItem}" />
</GridView.ItemTemplateSelector> </GridView.ItemTemplateSelector>-->
<GridView.ItemContainerStyle> <GridView.ItemContainerStyle>
<Style TargetType="FrameworkElement"> <Style TargetType="FrameworkElement">
<Setter Property="Margin" Value="52,0,0,2"/> <Setter Property="Margin" Value="52,0,0,2"/>
@@ -256,7 +300,6 @@
</ListView> </ListView>
</SemanticZoom.ZoomedOutView> </SemanticZoom.ZoomedOutView>
</SemanticZoom> </SemanticZoom>
</Grid> </Grid>
<!-- Back button and page title --> <!-- Back button and page title -->
<Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}"> <Grid Grid.Row="0" Background="{ThemeResource AppBarBackgroundThemeBrush}">
@@ -288,7 +331,7 @@
FontWeight="SemiBold" FontWeight="SemiBold"
TextWrapping="NoWrap" TextWrapping="NoWrap"
VerticalAlignment="Center" VerticalAlignment="Center"
PlaceholderText="New group name..."> x:Uid="GroupTitle">
<interactivity:Interaction.Behaviors> <interactivity:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="True"> <core:DataTriggerBehavior Binding="{Binding IsEditMode}" Value="True">
<actions:SetupFocusAction TargetObject="{Binding ElementName=TitleTextBox}" /> <actions:SetupFocusAction TargetObject="{Binding ElementName=TitleTextBox}" />
@@ -297,7 +340,7 @@
</TextBox> </TextBox>
<TextBlock FontSize="12" Text="{Binding Path}" /> <TextBlock FontSize="12" Text="{Binding Path}" />
</StackPanel> </StackPanel>
<SearchBox Grid.Column="2" PlaceholderText="Search..." Width="350" Background="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" BorderThickness="0" FontSize="18" SuggestionsRequested="SearchBox_OnSuggestionsRequested" SearchHistoryEnabled="False" ResultSuggestionChosen="SearchBox_OnResultSuggestionChosen" /> <SearchBox Grid.Column="2" x:Uid="GroupSearch" Width="350" Background="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" BorderThickness="0" FontSize="18" SuggestionsRequested="SearchBox_OnSuggestionsRequested" SearchHistoryEnabled="False" ResultSuggestionChosen="SearchBox_OnResultSuggestionChosen" />
</Grid> </Grid>
</Grid> </Grid>
</Page> </Page>

View File

@@ -99,9 +99,6 @@ namespace ModernKeePass.Pages
{ {
case -1: case -1:
return; return;
case 0:
entry = Model.AddNewEntry();
break;
default: default:
entry = GridView.SelectedItem as EntryVm; entry = GridView.SelectedItem as EntryVm;
break; break;
@@ -156,5 +153,10 @@ namespace ModernKeePass.Pages
} }
#endregion #endregion
private void CreateEntry_ButtonClick(object sender, RoutedEventArgs e)
{
Frame.Navigate(typeof(EntryDetailPage), Model.AddNewEntry());
}
} }
} }

View File

@@ -18,21 +18,21 @@
<Run Text="{Binding Version}" /> <Run Text="{Binding Version}" />
</TextBlock> </TextBlock>
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0"> <TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0">
<Run Text="A modern password manager for the Windows Store"/> <Run x:Uid="AboutDesc" />
</TextBlock> </TextBlock>
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0"> <TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0">
<Run Text="Homepage: "/> <Run x:Uid="AboutHomepage" />
<Hyperlink NavigateUri="https://github.com/wismna/ModernKeePass"> <Hyperlink NavigateUri="https://github.com/wismna/ModernKeePass">
<Run Text="https://github.com/wismna/ModernKeePass"/> <Run Text="https://github.com/wismna/ModernKeePass"/>
</Hyperlink></TextBlock> </Hyperlink></TextBlock>
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="10,0,0,0"> <TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="10,0,0,0">
<Run Text="Credits:"/> <Run x:Uid="AboutCreditsLabel" />
</TextBlock> </TextBlock>
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0"> <TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0">
<Run Text="Dominik Reichl for the KeePass application and file format"/> <Run x:Uid="AboutCredits1" />
</TextBlock> </TextBlock>
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0"> <TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="30,0,0,0">
<Run Text="David Lechner for his PCL adapatation of the KeePass Library and his correlated tests"/> <Run x:Uid="AboutCredits2" />
</TextBlock> </TextBlock>
</StackPanel> </StackPanel>
</Page> </Page>

View File

@@ -18,8 +18,8 @@
</Page.DataContext> </Page.DataContext>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<HyperlinkButton Content="Create new..." Click="ButtonBase_OnClick" /> <HyperlinkButton x:Uid="NewCreateButton" Click="ButtonBase_OnClick" />
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">Create a new password database to the location of your chosing.</TextBlock> <TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" x:Uid="NewCreateDesc" />
<Border HorizontalAlignment="Left" BorderThickness="1" BorderBrush="AliceBlue" Width="550" Visibility="{Binding ShowPasswordBox, Converter={StaticResource BooleanToVisibilityConverter}}"> <Border HorizontalAlignment="Left" BorderThickness="1" BorderBrush="AliceBlue" Width="550" Visibility="{Binding ShowPasswordBox, Converter={StaticResource BooleanToVisibilityConverter}}">
<StackPanel Margin="25,0,25,0"> <StackPanel Margin="25,0,25,0">
<TextBlock Text="{Binding Name}" /> <TextBlock Text="{Binding Name}" />

View File

@@ -17,10 +17,10 @@
</Page.DataContext> </Page.DataContext>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<HyperlinkButton Content="Browse files..." Click="ButtonBase_OnClick" /> <HyperlinkButton x:Uid="OpenBrowseButton" Click="ButtonBase_OnClick" />
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">Open an existing password database from your PC.</TextBlock> <TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" x:Uid="OpenBrowseDesc" />
<HyperlinkButton Content="From Url..." IsEnabled="False" /> <HyperlinkButton x:Uid="OpenUrlButton" IsEnabled="False" />
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">Open an existing password database from an Internet location (not yet implemented).</TextBlock> <TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" x:Uid="OpenUrlDesc" />
<Border HorizontalAlignment="Left" BorderThickness="1" BorderBrush="AliceBlue" Width="550" Visibility="{Binding ShowPasswordBox, Converter={StaticResource BooleanToVisibilityConverter}}"> <Border HorizontalAlignment="Left" BorderThickness="1" BorderBrush="AliceBlue" Width="550" Visibility="{Binding ShowPasswordBox, Converter={StaticResource BooleanToVisibilityConverter}}">
<StackPanel Margin="25,0,25,0"> <StackPanel Margin="25,0,25,0">
<TextBlock Text="{Binding Name}" /> <TextBlock Text="{Binding Name}" />

View File

@@ -11,9 +11,9 @@
</Page.DataContext> </Page.DataContext>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<HyperlinkButton Content="Save and close" Click="SaveButton_OnClick" /> <HyperlinkButton x:Uid="SaveButton" Click="SaveButton_OnClick" />
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">This will save and close the currently opened database.</TextBlock> <TextBlock x:Uid="SaveDesc" Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" />
<HyperlinkButton Content="Save as..." Click="SaveAsButton_OnClick" /> <HyperlinkButton x:Uid="SaveAsButton" Click="SaveAsButton_OnClick" />
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30">This will save the currently opened database as a new file and leave it open.</TextBlock> <TextBlock x:Uid="SaveAsDesc" Style="{StaticResource BodyTextBlockStyle}" Margin="15,0,0,30" />
</StackPanel> </StackPanel>
</Page> </Page>

View File

@@ -9,11 +9,11 @@
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Orientation="Horizontal" Margin="0,2,0,10"> <StackPanel Orientation="Horizontal" Margin="0,2,0,10">
<SymbolIcon Symbol="Back" Margin="0,7,40,0" /> <SymbolIcon Symbol="Back" Margin="0,7,40,0" />
<TextBlock Style="{StaticResource SubheaderTextBlockStyle}">Have an existing password database? Open it here.</TextBlock> <TextBlock Style="{StaticResource SubheaderTextBlockStyle}" x:Uid="WelcomeOpen" />
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,6,0,10"> <StackPanel Orientation="Horizontal" Margin="0,6,0,10">
<SymbolIcon Symbol="Back" Margin="0,7,40,0" /> <SymbolIcon Symbol="Back" Margin="0,7,40,0" />
<TextBlock Style="{StaticResource SubheaderTextBlockStyle}">Want to create a new password database? Do it here.</TextBlock> <TextBlock Style="{StaticResource SubheaderTextBlockStyle}" x:Uid="WelcomeNew" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
</Page> </Page>

View File

@@ -17,13 +17,13 @@
</Page.DataContext> </Page.DataContext>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ToggleSwitch Header="Recycle bin" OffContent="Disabled" OnContent="Enabled" IsOn="{Binding HasRecycleBin, Mode=TwoWay}" /> <ToggleSwitch x:Uid="SettingsDatabaseRecycleBin" IsOn="{Binding HasRecycleBin, Mode=TwoWay}" />
<ComboBox ItemsSource="{Binding Source={StaticResource RecycleBinGroups}}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" IsEnabled="{Binding HasRecycleBin}" /> <ComboBox ItemsSource="{Binding Source={StaticResource RecycleBinGroups}}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" IsEnabled="{Binding HasRecycleBin}" />
<TextBlock Text="Encryption Algorithm" FontSize="14" Margin="5,20,0,10" /> <TextBlock x:Uid="SettingsDatabaseEncryption" FontSize="14" Margin="5,20,0,10" />
<ComboBox ItemsSource="{Binding Source={StaticResource Ciphers}}" SelectedIndex="{Binding CipherIndex, Mode=TwoWay}" /> <ComboBox ItemsSource="{Binding Source={StaticResource Ciphers}}" SelectedIndex="{Binding CipherIndex, Mode=TwoWay}" />
<TextBlock Text="Compression Algorithm" FontSize="14" Margin="5,20,0,10" /> <TextBlock x:Uid="SettingsDatabaseCompression" FontSize="14" Margin="5,20,0,10" />
<ComboBox ItemsSource="{Binding Source={StaticResource Compressions}}" SelectedItem="{Binding CompressionName, Mode=TwoWay}" /> <ComboBox ItemsSource="{Binding Source={StaticResource Compressions}}" SelectedItem="{Binding CompressionName, Mode=TwoWay}" />
<TextBlock Text="Key Derivation Algorithm" FontSize="14" Margin="5,20,0,10" /> <TextBlock x:Uid="SettingsDatabaseKdf" FontSize="14" Margin="5,20,0,10" />
<ComboBox ItemsSource="{Binding Source={StaticResource KeyDerivations}}" SelectedItem="{Binding KeyDerivationName, Mode=TwoWay}" /> <ComboBox ItemsSource="{Binding Source={StaticResource KeyDerivations}}" SelectedItem="{Binding KeyDerivationName, Mode=TwoWay}" />
</StackPanel> </StackPanel>
</Page> </Page>

View File

@@ -8,12 +8,12 @@
mc:Ignorable="d"> mc:Ignorable="d">
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock FontSize="14" Text="Change database security options" Margin="5,0,0,0" /> <TextBlock x:Uid="SettingsSecurityTitle" FontSize="14" Margin="5,0,0,0" />
<TextBlock TextWrapping="WrapWholeWords" Margin="5,0,0,0"> <TextBlock TextWrapping="WrapWholeWords" Margin="5,0,0,0">
<Run Text="Here, you may change your database password, key file, or both. Just click on on" /> <Run x:Uid="SettingsSecurityDesc1" />
<Run Text="Update master key" FontWeight="SemiBold" /> <Run x:Uid="SettingsSecurityDesc2" FontWeight="SemiBold" />
<Run Text="when you're done. Please make sure to remember the password you choose here!" /> <Run x:Uid="SettingsSecurityDesc3" />
</TextBlock> </TextBlock>
<local:CompositeKeyUserControl Margin="0,20,0,0" UpdateKey="True" ButtonLabel="Update master key" ValidationChecked="CompositeKeyUserControl_OnValidationChecked" /> <local:CompositeKeyUserControl Margin="0,20,0,0" UpdateKey="True" x:Uid="SettingsSecurityUpdateButton" ValidationChecked="CompositeKeyUserControl_OnValidationChecked" />
</StackPanel> </StackPanel>
</Page> </Page>

View File

@@ -7,8 +7,8 @@
mc:Ignorable="d"> mc:Ignorable="d">
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock FontSize="24" VerticalAlignment="Center" Margin="10,-70,0,0" Text="Settings" /> <TextBlock FontSize="24" VerticalAlignment="Center" Margin="10,-70,0,0" x:Uid="SettingsWelcomeTitle" />
<TextBlock VerticalAlignment="Center" FontSize="14" Margin="5,0,0,0" Text="Here, you may change the application or the database settings." /> <TextBlock VerticalAlignment="Center" FontSize="14" Margin="5,0,0,0" x:Uid="SettingsWelcomeDesc" />
<TextBlock VerticalAlignment="Center" FontSize="14" Margin="5,0,0,0" Text="Select a setting pane on the left to access the options." /> <TextBlock VerticalAlignment="Center" FontSize="14" Margin="5,0,0,0" x:Uid="SettingsWelcomeHowto" />
</StackPanel> </StackPanel>
</Page> </Page>

View File

@@ -0,0 +1,282 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AboutCredits1.Text" xml:space="preserve">
<value>Dominik Reichl for the KeePass application and file format</value>
</data>
<data name="AboutCredits2.Text" xml:space="preserve">
<value>David Lechner for his PCL adapatation of the KeePass Library and his correlated tests</value>
</data>
<data name="AboutCreditsLabel.Text" xml:space="preserve">
<value>Credits</value>
</data>
<data name="AboutDesc.Text" xml:space="preserve">
<value>A modern password manager for the Windows Store</value>
</data>
<data name="AboutHomepage.Text" xml:space="preserve">
<value>Homepage:</value>
</data>
<data name="CompositeKeyNewKeyFileTooltip.Content" xml:space="preserve">
<value>Create new key file</value>
</data>
<data name="CompositeKeyPassword.PlaceholderText" xml:space="preserve">
<value>Password</value>
</data>
<data name="EntryExpirationDate.Content" xml:space="preserve">
<value>Expiration date</value>
</data>
<data name="EntryExpirationTooltip.Content" xml:space="preserve">
<value>Password has expired</value>
</data>
<data name="EntryLogin.Text" xml:space="preserve">
<value>User name or login</value>
</data>
<data name="EntryNotes.Text" xml:space="preserve">
<value>Notes</value>
</data>
<data name="EntryPassword.Text" xml:space="preserve">
<value>Password</value>
</data>
<data name="EntryShowPassword.Content" xml:space="preserve">
<value>Show password</value>
</data>
<data name="GroupCreateEntry.Text" xml:space="preserve">
<value>Create new entry</value>
</data>
<data name="GroupSearch.PlaceholderText" xml:space="preserve">
<value>Search...</value>
</data>
<data name="GroupTitle.PlaceholderText" xml:space="preserve">
<value>New group name...</value>
</data>
<data name="NewCreateButton.Content" xml:space="preserve">
<value>Create new...</value>
</data>
<data name="NewCreateDesc.Text" xml:space="preserve">
<value>Create a new password database to the location of your chosing.</value>
</data>
<data name="OpenBrowseButton.Content" xml:space="preserve">
<value>Browse files...</value>
</data>
<data name="OpenBrowseDesc.Text" xml:space="preserve">
<value>Open an existing password database from your PC.</value>
</data>
<data name="OpenUrlButton.Content" xml:space="preserve">
<value>From Url...</value>
</data>
<data name="OpenUrlDesc.Text" xml:space="preserve">
<value>Open an existing password database from an Internet location (not yet implemented).</value>
</data>
<data name="PasswordGeneratorAlso.Text" xml:space="preserve">
<value>Also add these characters:</value>
</data>
<data name="PasswordGeneratorBrackets.Content" xml:space="preserve">
<value>Brackets ([], {}, (), ...)</value>
</data>
<data name="PasswordGeneratorButton.Content" xml:space="preserve">
<value>Generate</value>
</data>
<data name="PasswordGeneratorDigits.Content" xml:space="preserve">
<value>Digits (0, 1, 2, ...)</value>
</data>
<data name="PasswordGeneratorLength.Text" xml:space="preserve">
<value>Password Length:</value>
</data>
<data name="PasswordGeneratorLower.Content" xml:space="preserve">
<value>Lower case (a, b, c, ...)</value>
</data>
<data name="PasswordGeneratorMinus.Content" xml:space="preserve">
<value>Minus (-)</value>
</data>
<data name="PasswordGeneratorSpace.Content" xml:space="preserve">
<value>Space ( )</value>
</data>
<data name="PasswordGeneratorSpecial.Content" xml:space="preserve">
<value>Special (!, $, %, ...)</value>
</data>
<data name="PasswordGeneratorTooltip.Content" xml:space="preserve">
<value>Generate password</value>
</data>
<data name="PasswordGeneratorUnderscore.Content" xml:space="preserve">
<value>Underscore (_)</value>
</data>
<data name="PasswordGeneratorUpper.Content" xml:space="preserve">
<value>Upper case (A, B, C, ...)</value>
</data>
<data name="SaveAsButton.Content" xml:space="preserve">
<value>Save as...</value>
</data>
<data name="SaveAsDesc.Text" xml:space="preserve">
<value>This will save the currently opened database as a new file and leave it open.</value>
</data>
<data name="SaveButton.Content" xml:space="preserve">
<value>Save and close</value>
</data>
<data name="SaveDesc.Text" xml:space="preserve">
<value>This will save and close the currently opened database.</value>
</data>
<data name="SettingsDatabaseCompression.Text" xml:space="preserve">
<value>Compression Algorithm</value>
</data>
<data name="SettingsDatabaseEncryption.Text" xml:space="preserve">
<value>Encryption Algorithm</value>
</data>
<data name="SettingsDatabaseKdf.Text" xml:space="preserve">
<value>Key Derivation Algorithm</value>
</data>
<data name="SettingsDatabaseRecycleBin.Header" xml:space="preserve">
<value>Recycle bin</value>
</data>
<data name="SettingsDatabaseRecycleBin.OffContent" xml:space="preserve">
<value>Disabled</value>
</data>
<data name="SettingsDatabaseRecycleBin.OnContent" xml:space="preserve">
<value>Enabled</value>
</data>
<data name="SettingsSecurityDesc1.Text" xml:space="preserve">
<value>Here, you may change your database password, key file, or both. Just click on on</value>
</data>
<data name="SettingsSecurityDesc2.Text" xml:space="preserve">
<value>Update master key</value>
</data>
<data name="SettingsSecurityDesc3.Text" xml:space="preserve">
<value>when you're done. Please make sure to remember the password you choose here!</value>
</data>
<data name="SettingsSecurityTitle.Text" xml:space="preserve">
<value>Change database security options</value>
</data>
<data name="SettingsSecurityUpdateButton.ButtonLabel" xml:space="preserve">
<value>Update master key</value>
</data>
<data name="SettingsWelcomeDesc.Text" xml:space="preserve">
<value>Here, you may change the application or the database settings.</value>
</data>
<data name="SettingsWelcomeHowto.Text" xml:space="preserve">
<value>Select a setting pane on the left to access the options.</value>
</data>
<data name="SettingsWelcomeTitle.Text" xml:space="preserve">
<value>Settings</value>
</data>
<data name="WelcomeNew.Text" xml:space="preserve">
<value>Want to create a new password database? Do it here.</value>
</data>
<data name="WelcomeOpen.Text" xml:space="preserve">
<value>Have an existing password database? Open it here.</value>
</data>
</root>

View File

@@ -226,7 +226,6 @@ namespace ModernKeePass.ViewModels
{ {
PreviousGroup = ParentGroup; PreviousGroup = ParentGroup;
PreviousGroup.Entries.Remove(this); PreviousGroup.Entries.Remove(this);
PreviousGroup.RemovePwEntry(_pwEntry);
if (destination == null) if (destination == null)
{ {
_database.AddDeletedItem(IdUuid); _database.AddDeletedItem(IdUuid);
@@ -234,19 +233,22 @@ namespace ModernKeePass.ViewModels
} }
ParentGroup = destination; ParentGroup = destination;
ParentGroup.Entries.Add(this); ParentGroup.Entries.Add(this);
ParentGroup.AddPwEntry(_pwEntry);
} }
public void CommitDelete() public void CommitDelete()
{ {
_pwEntry.ParentGroup.Entries.Remove(_pwEntry); _pwEntry.ParentGroup.Entries.Remove(_pwEntry);
if (_database.RecycleBinEnabled && !PreviousGroup.IsSelected) _database.RecycleBin.AddPwEntry(_pwEntry); if (!_database.RecycleBinEnabled || PreviousGroup.IsSelected) _database.AddDeletedItem(IdUuid);
else _database.AddDeletedItem(IdUuid);
} }
public void Save() public void Save()
{ {
_database.Save(); _database.Save();
} }
public PwEntry GetPwEntry()
{
return _pwEntry;
}
} }
} }

View File

@@ -1,4 +1,6 @@
using System.Collections.ObjectModel; using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Windows.UI.Text; using Windows.UI.Text;
@@ -82,6 +84,7 @@ namespace ModernKeePass.ViewModels
private readonly PwGroup _pwGroup; private readonly PwGroup _pwGroup;
private readonly IDatabase _database; private readonly IDatabase _database;
private bool _isEditMode; private bool _isEditMode;
private PwEntry _reorderedEntry;
public GroupVm() {} public GroupVm() {}
@@ -96,12 +99,28 @@ namespace ModernKeePass.ViewModels
ParentGroup = parent; ParentGroup = parent;
if (recycleBinId != null && _pwGroup.Uuid.Equals(recycleBinId)) _database.RecycleBin = this; if (recycleBinId != null && _pwGroup.Uuid.Equals(recycleBinId)) _database.RecycleBin = this;
Entries = new ObservableCollection<EntryVm>(pwGroup.Entries.Select(e => new EntryVm(e, this)).OrderBy(e => e.Name)); Entries = new ObservableCollection<EntryVm>(pwGroup.Entries.Select(e => new EntryVm(e, this)));
Entries.Insert(0, new EntryVm ()); Entries.CollectionChanged += Entries_CollectionChanged;
Groups = new ObservableCollection<GroupVm>(pwGroup.Groups.Select(g => new GroupVm(g, this, recycleBinId)).OrderBy(g => g.Name)); Groups = new ObservableCollection<GroupVm>(pwGroup.Groups.Select(g => new GroupVm(g, this, recycleBinId)));
Groups.Insert(0, new GroupVm ()); Groups.Insert(0, new GroupVm ());
} }
private void Entries_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Remove:
var oldIndex = (uint) e.OldStartingIndex;
_reorderedEntry = _pwGroup.Entries.GetAt(oldIndex);
_pwGroup.Entries.RemoveAt(oldIndex);
break;
case NotifyCollectionChangedAction.Add:
if (e.OldStartingIndex == -1) _pwGroup.Entries.Add(((EntryVm)e.NewItems[0]).GetPwEntry());
else _pwGroup.Entries.Insert((uint)e.NewStartingIndex, _reorderedEntry);
break;
}
}
public GroupVm AddNewGroup(string name = "") public GroupVm AddNewGroup(string name = "")
{ {
var pwGroup = new PwGroup(true, true, name, PwIcon.Folder); var pwGroup = new PwGroup(true, true, name, PwIcon.Folder);
@@ -114,23 +133,12 @@ namespace ModernKeePass.ViewModels
public EntryVm AddNewEntry() public EntryVm AddNewEntry()
{ {
var pwEntry = new PwEntry(true, true); var pwEntry = new PwEntry(true, true);
_pwGroup.AddEntry(pwEntry, true);
var newEntry = new EntryVm(pwEntry, this) {IsEditMode = true}; var newEntry = new EntryVm(pwEntry, this) {IsEditMode = true};
newEntry.GeneratePassword(); newEntry.GeneratePassword();
Entries.Add(newEntry); Entries.Add(newEntry);
return newEntry; return newEntry;
} }
public void AddPwEntry(PwEntry entry)
{
_pwGroup.AddEntry(entry, true);
}
public void RemovePwEntry(PwEntry entry)
{
_pwGroup.Entries.Remove(entry);
}
public void MarkForDelete() public void MarkForDelete()
{ {
if (_database.RecycleBinEnabled && _database.RecycleBin?.IdUuid == null) if (_database.RecycleBinEnabled && _database.RecycleBin?.IdUuid == null)
@@ -171,6 +179,19 @@ namespace ModernKeePass.ViewModels
_database.Save(); _database.Save();
} }
public void SortEntries()
{
var comparer = new PwEntryComparer(PwDefs.TitleField, true, true);
try
{
_pwGroup.Entries.Sort(comparer);
Entries = new ObservableCollection<EntryVm>(Entries.OrderBy(e => e.Name));
}
catch (Exception e)
{
}
}
public override string ToString() public override string ToString()
{ {
return Name; return Name;