worked some more on the ui, added some more input sanitisation and some more buttons that are actually working!

close to abgabe yo
This commit is contained in:
taarly 2025-06-30 19:48:36 +02:00
parent f86465ff71
commit 6329e63310
11 changed files with 186 additions and 71 deletions

View File

@ -7,7 +7,11 @@ public partial class SQLite
//filepath for home-pc: //filepath for home-pc:
//private static string _dbPath = "C:/Users/Soi/Desktop/keywi.db"; //private static string _dbPath = "C:/Users/Soi/Desktop/keywi.db";
//filepath for work-laptop: //filepath for work-laptop:
private static string _dbPath = "C:/Users/lowns/Desktop/keywi.db"; private static string _dbPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"keywi.db"
);
//KLASSENVARIABLEN ERSTELLEN //KLASSENVARIABLEN ERSTELLEN
//private static string loginname; //private static string loginname;

View File

@ -5,6 +5,7 @@ using Avalonia.Media;
using Project.Controller; using Project.Controller;
using Project.Model; using Project.Model;
using Project.Persistence; using Project.Persistence;
namespace Project.View; namespace Project.View;
public partial class EntryErrorPopUp : Window public partial class EntryErrorPopUp : Window

View File

@ -1,7 +1,9 @@
<UserControl <UserControl
x:Class="Project.View.LoginPage" x:Class="Project.View.LoginPage"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<UserControl.Styles> <UserControl.Styles>
<Style Selector="Button"> <Style Selector="Button">
@ -30,7 +32,8 @@
BoxShadow="0 4 8 0 #40000000" BoxShadow="0 4 8 0 #40000000"
CornerRadius="8" CornerRadius="8"
Padding="20" Padding="20"
Width="400"> Width="400"
Height="600">
<StackPanel> <StackPanel>
<Image <Image

View File

@ -1,9 +1,11 @@
using System;
using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Media; using Avalonia.Media;
using Project.Controller; using Project.Controller;
using Project.View; using Project.Model;
using System.Threading.Tasks; using Project.Persistence;
namespace Project.View; namespace Project.View;
@ -22,18 +24,28 @@ public partial class LoginPage : UserControl
//gives loginname and password over to the appcontroller to compare the logins //gives loginname and password over to the appcontroller to compare the logins
private async void LoginButtonOnClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e) private async void LoginButtonOnClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{ {
string? loginName = LoginNameBox.Text ?? string.Empty; string loginName = LoginNameBox.Text.Trim() ?? string.Empty;
string? loginPassword = LoginPasswordBox.Text ?? string.Empty; string loginPassword = LoginPasswordBox.Text.Trim() ?? string.Empty;
bool allowLogin = AppController.CompareLogin(loginName, loginPassword); bool allowLogin = AppController.CompareLogin(loginName, loginPassword);
var newPopUp = new LoginErrorPopUp(); var newPopUp = new LoginErrorPopUp();
if (allowLogin) if (allowLogin)
{ {
//show menuview //show menuview
AppController.SetCurrentUser(loginName); AppController.SetCurrentUser(loginName);
//await Task.Delay(300); // 1 second delay until menu gets shown //await Task.Delay(1000); // 1 second delay until menu gets shown
var newMenuView = new MenuView(); var newMenuView = new MenuView();
newMenuView.Show(); newMenuView.Show();
// close window
if (this.Parent is Grid grid && grid.Parent is MainWindow mainWindow)
{
mainWindow.Close();
}
} }
else else
{ {
@ -42,6 +54,8 @@ public partial class LoginPage : UserControl
LoginPasswordBox.Text = string.Empty; LoginPasswordBox.Text = string.Empty;
} }
} }
//opens the window to create a new user
private async void NewUserButtonOnClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e) private async void NewUserButtonOnClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{ {
var newLoginWindow = new NewLogin(); var newLoginWindow = new NewLogin();

View File

@ -5,6 +5,7 @@ using Avalonia.Media;
using Project.Controller; using Project.Controller;
using Project.Model; using Project.Model;
using Project.Persistence; using Project.Persistence;
namespace Project.View; namespace Project.View;
public partial class LoginErrorPopUp : Window public partial class LoginErrorPopUp : Window

View File

@ -2,10 +2,13 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" Height="700"
Width="500"
WindowStartupLocation="CenterScreen"
x:Class="Project.View.MainWindow" x:Class="Project.View.MainWindow"
xmlns:views="clr-namespace:Project.View" xmlns:views="clr-namespace:Project.View"
Title="Project.View"> Title="KEYWI - your password manager!">
<Grid Name="MainGrid"> <Grid Name="MainGrid">

View File

@ -1,11 +1,14 @@
<UserControl <UserControl
x:Class="Project.View.MenuView" x:Class="Project.View.MenuView"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="400"
Width="800">
<UserControl.Styles> <UserControl.Styles>
<Style Selector="TextBlock"> <Style Selector="TextBlock">
<Setter Property="FontSize" Value="16" /> <Setter Property="FontSize" Value="16" />
<Setter Property="Foreground" Value= "Gray" />
<Setter Property="Margin" Value="0,10" /> <Setter Property="Margin" Value="0,10" />
</Style> </Style>
<Style Selector="TextBox"> <Style Selector="TextBox">
@ -68,45 +71,23 @@
<!-- Right column --> <!-- Right column -->
<Border Background="White" Grid.Column="1"> <Border Background="White" Grid.Column="1">
<StackPanel Margin="40" x:Name="ShowEntryDetails"> <StackPanel Margin="40">
<Grid ColumnDefinitions="150,*"> <Grid ColumnDefinitions="150,*">
<!-- Labels --> <!-- Labels -->
<StackPanel Grid.Column="0"> <StackPanel Grid.Column="0" x:Name="ShowEntryDetailsL">
<TextBlock FontWeight="SemiBold" Text="Name:" />
<TextBlock FontWeight="SemiBold" Text="Login-Name:" />
<TextBlock FontWeight="SemiBold" Text="URL:" />
<TextBlock FontWeight="SemiBold" Text="Password:" />
<TextBlock FontWeight="SemiBold" Text="Note:" />
</StackPanel> </StackPanel>
<!-- entry fields --> <!-- entry fields -->
<StackPanel Grid.Column="1"> <StackPanel Grid.Column="1" x:Name="ShowEntryDetailsR">
<TextBox Text="THE NAME OF YOUR SAVED LOGIN" /> <Image
<TextBox Text="YOUR LOGIN NAME ON THIS PAGE" /> Height="300"
<TextBox Text="THE URL TO YOUR PAGE" /> Margin="0,0,0,0"
Source="avares://Project.View/Images/keywi_logo_2.png"
<StackPanel Orientation="Horizontal"> Width="300" />
<TextBox
PasswordChar="•"
Text="PASSWORT"
Width="250" />
<Button
Classes="icon"
Content="📋"
ToolTip.Tip="Passwort kopieren"
x:Name="copyPassword" />
<Button
Classes="icon"
Content="👁"
ToolTip.Tip="Passwort anzeigen"
x:Name="showPassword" />
</StackPanel>
<TextBox
AcceptsReturn="True"
Height="150"
Text="YOUR NOTES" />
</StackPanel> </StackPanel>
</Grid> </Grid>
</StackPanel> </StackPanel>

View File

@ -5,6 +5,8 @@ using Avalonia.Media;
using Project.Controller; using Project.Controller;
using Project.Model; using Project.Model;
using Project.Persistence; using Project.Persistence;
using Avalonia.Input.Platform; // Fügen Sie diese Zeile am Anfang der Datei hinzu
using System.Threading.Tasks;
namespace Project.View; namespace Project.View;
@ -16,7 +18,8 @@ public partial class MenuView : Window
{ {
InitializeComponent(); InitializeComponent();
CreateEntryButtons(); CreateEntryButtons();
Title = "KEYWI - your password manager!";
} }
public MenuView(AppController controller) public MenuView(AppController controller)
@ -26,6 +29,7 @@ public partial class MenuView : Window
} }
//opens the window to create a new entry
private async void NewEntryButton_OnClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e) private async void NewEntryButton_OnClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{ {
var newEntryWindow = new NewEntry(); var newEntryWindow = new NewEntry();
@ -60,39 +64,136 @@ public partial class MenuView : Window
CreateEntryButtons(); CreateEntryButtons();
} }
//shows the details for the selected entry
public void EntryDetails(SavedEntries entry) public void EntryDetails(SavedEntries entry)
{ {
ShowEntryDetails.Children.Clear(); // ... vorheriger Code bleibt gleich bis zur PasswordBox ...
ShowEntryDetailsL.Children.Clear();
ShowEntryDetailsR.Children.Clear();
ShowEntryDetails.Children.Add(new TextBlock ShowEntryDetailsL.Children.Add(new TextBlock
{ {
Text = $"Name: {entry.Name}", Text = $"Name:",
Margin = new Thickness(0, 0, 0, 5) Margin = new Thickness(0, 0, 0, 5)
}); });
ShowEntryDetails.Children.Add(new TextBlock ShowEntryDetailsL.Children.Add(new TextBlock
{ {
Text = $"Email/Username: {entry.MailUsername}", Text = $"Email/Username:",
Margin = new Thickness(0, 0, 0, 5) Margin = new Thickness(0, 0, 0, 5)
}); });
ShowEntryDetails.Children.Add(new TextBlock ShowEntryDetailsL.Children.Add(new TextBlock
{ {
Text = $"URL: {entry.Url}", Text = $"URL:",
Margin = new Thickness(0, 0, 0, 5) Margin = new Thickness(0, 0, 0, 5)
}); });
ShowEntryDetails.Children.Add(new TextBlock ShowEntryDetailsL.Children.Add(new TextBlock
{ {
Text = $"Password: {Crypto.DecryptPassword(entry.Pass)}", Text = $"Password:",
Margin = new Thickness(0, 0, 0, 5)
});
ShowEntryDetailsL.Children.Add(new TextBlock
{
Text = $"Note:",
Margin = new Thickness(0, 0, 0, 5)
});
ShowEntryDetailsR.Children.Add(new TextBox()
{
Text = $"{entry.Name}",
Margin = new Thickness(0, 0, 0, 5)
});
ShowEntryDetailsR.Children.Add(new TextBox()
{
Text = $"{entry.MailUsername}",
Margin = new Thickness(0, 0, 0, 5)
});
ShowEntryDetailsR.Children.Add(new TextBox()
{
Text = $"{entry.Url}",
Margin = new Thickness(0, 0, 0, 5) Margin = new Thickness(0, 0, 0, 5)
}); });
var passwordBox = new TextBox
{
Name = "LoginPasswordBox",
PasswordChar = '•',
Text = Crypto.EncryptPassword(entry.Pass),
Margin = new Thickness(0, 0, 0, 5)
};
ShowEntryDetailsR.Children.Add(passwordBox);
//dynamically creating a new horizontal stackpanel
var buttonContainer = new StackPanel
{
Orientation = Avalonia.Layout.Orientation.Horizontal,
Spacing = 5
};
//creating 2 buttons next to each other to show/hide and copy password
var showPasswordButton = new Button
{
Width = 40,
Height = 30,
Content = "👁"
};
var copyPasswordButton = new Button
{
Width = 40,
Height = 30,
Content = "📋"
};
//on click events for both buttons
showPasswordButton.Click += (sender, args) =>
{
if (passwordBox.PasswordChar == '•')
{
passwordBox.Text = Crypto.DecryptPassword(entry.Pass);
passwordBox.PasswordChar = '\0';
}
else
{
passwordBox.Text = Crypto.EncryptPassword(entry.Pass);
passwordBox.PasswordChar = '•';
}
};
copyPasswordButton.Click += async (sender, args) =>
{
var clipboard = TopLevel.GetTopLevel(this)?.Clipboard;
if (clipboard != null)
{
await clipboard.SetTextAsync(Crypto.DecryptPassword(entry.Pass));
// Visuelle Bestätigung
copyPasswordButton.Content = "✓";
await Task.Delay(1000);
copyPasswordButton.Content = "📋";
}
};
buttonContainer.Children.Add(showPasswordButton);
buttonContainer.Children.Add(copyPasswordButton);
ShowEntryDetailsR.Children.Add(buttonContainer);
if (!string.IsNullOrEmpty(entry.Note)) if (!string.IsNullOrEmpty(entry.Note))
{ {
ShowEntryDetails.Children.Add(new TextBlock ShowEntryDetailsR.Children.Add(new TextBox()
{ {
Text = $"Note: {entry.Note}", Text = $"{entry.Note}",
Margin = new Thickness(0, 0, 0, 5) Margin = new Thickness(0, 0, 0, 5)
}); });
} }
} }
} }

View File

@ -13,6 +13,7 @@ public partial class NewEntry : Window
{ {
InitializeComponent(); InitializeComponent();
this.SizeToContent = SizeToContent.Height; this.SizeToContent = SizeToContent.Height;
Title = "KEYWI - your password manager!";
} }
public NewEntry(AppController controller) public NewEntry(AppController controller)
@ -25,6 +26,7 @@ public partial class NewEntry : Window
Close(); Close();
} }
//saves the new entry to the database on click
private void NewEntry_Save_Click(object? sender, RoutedEventArgs e) private void NewEntry_Save_Click(object? sender, RoutedEventArgs e)
{ {
string? name = NameBox.Text; string? name = NameBox.Text;
@ -32,6 +34,7 @@ public partial class NewEntry : Window
string? url = URLBox.Text; string? url = URLBox.Text;
string? pass = PassBox.Text; string? pass = PassBox.Text;
string? note = NoteBox.Text; string? note = NoteBox.Text;
//test inputs:
if (InputSanitizer.EntryName(name) && InputSanitizer.Password(pass) && InputSanitizer.Userormail(username)) if (InputSanitizer.EntryName(name) && InputSanitizer.Password(pass) && InputSanitizer.Userormail(username))
{ {
AppController.NewEntrySave(name, username, url, pass, note); AppController.NewEntrySave(name, username, url, pass, note);
@ -51,7 +54,7 @@ public partial class NewEntry : Window
} }
} }
//shows the password or hides it again
private void NewEntry_ShowPW_Click(object? sender, RoutedEventArgs e) private void NewEntry_ShowPW_Click(object? sender, RoutedEventArgs e)
{ {
if (NewentryPW.PasswordChar == '•') if (NewentryPW.PasswordChar == '•')

View File

@ -3,7 +3,8 @@
Width="400" Width="400"
x:Class="Project.View.NewLogin" x:Class="Project.View.NewLogin"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<UserControl.Styles> <UserControl.Styles>
<Style Selector="TextBlock"> <Style Selector="TextBlock">
@ -31,8 +32,8 @@
<Grid> <Grid>
<Grid.Background> <Grid.Background>
<LinearGradientBrush EndPoint="1,1" StartPoint="0,0"> <LinearGradientBrush EndPoint="1,1" StartPoint="0,0">
<GradientStop Color="#FFE0B2" Offset="0" /> <GradientStop Color="White" Offset="0" />
<GradientStop Color="#FFCC80" Offset="1" /> <GradientStop Color="LightGray" Offset="1" />
</LinearGradientBrush> </LinearGradientBrush>
</Grid.Background> </Grid.Background>
@ -48,36 +49,36 @@
FontWeight="Bold" FontWeight="Bold"
HorizontalAlignment="Center" HorizontalAlignment="Center"
Margin="0,0,0,20" Margin="0,0,0,20"
Text="Neuer Benutzer" /> Text="New user" />
<TextBlock Text="Benutzername:" /> <TextBlock Text="Username:" />
<TextBox <TextBox
TextWrapping="Wrap" TextWrapping="Wrap"
Watermark="Benutzername eingeben" Watermark="Enter Username"
x:Name="NewLoginUsernameBox" /> x:Name="NewLoginUsernameBox" />
<TextBlock Text="Passwort:" /> <TextBlock Text="Password:" />
<TextBox <TextBox
PasswordChar="•" PasswordChar="•"
TextWrapping="Wrap" TextWrapping="Wrap"
Watermark="Passwort eingeben" Watermark="Enter password"
x:Name="NewLoginPasswordBox" /> x:Name="NewLoginPasswordBox" />
<TextBlock Text="E-Mail:" /> <TextBlock Text="E-Mail:" />
<TextBox <TextBox
TextWrapping="Wrap" TextWrapping="Wrap"
Watermark="E-Mail-Adresse eingeben" Watermark="Enter email"
x:Name="NewLoginEmailBox" /> x:Name="NewLoginEmailBox" />
<StackPanel <StackPanel
HorizontalAlignment="Center" HorizontalAlignment="Center"
Margin="0,20,0,0" Margin="0,20,0,0"
Orientation="Horizontal"> Orientation="Horizontal">
<Button Click="NewLoginSaveOnClick" Content="Speichern" /> <Button Click="NewLoginSaveOnClick" Content="Save" />
<Button <Button
Background="#FF5722" Background="#FF5722"
Click="NewLoginCancelOnClick" Click="NewLoginCancelOnClick"
Content="Abbrechen" /> Content="Cancel" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
</Border> </Border>

View File

@ -15,6 +15,7 @@ public partial class NewLogin : Window
{ {
InitializeComponent(); InitializeComponent();
_controller = new(); _controller = new();
Title = "KEYWI - your password manager!";
} }
public NewLogin(AppController controller) public NewLogin(AppController controller)
@ -23,6 +24,7 @@ public partial class NewLogin : Window
_controller = controller; _controller = controller;
} }
//saves the new user to the database
private void NewLoginSaveOnClick(object? sender, RoutedEventArgs e) private void NewLoginSaveOnClick(object? sender, RoutedEventArgs e)
{ {
string username = NewLoginUsernameBox.Text?.Trim() ?? string.Empty; string username = NewLoginUsernameBox.Text?.Trim() ?? string.Empty;
@ -49,6 +51,7 @@ public partial class NewLogin : Window
} }
} }
//closes the window on click
private void NewLoginCancelOnClick(object? sender, RoutedEventArgs e) private void NewLoginCancelOnClick(object? sender, RoutedEventArgs e)
{ {
Close(); Close();