Hide token using password box

This commit is contained in:
Tyrrrz 2023-07-09 18:13:41 +03:00
parent 51192425b7
commit c4137cf77e
7 changed files with 95 additions and 31 deletions

View file

@ -31,12 +31,12 @@ public class Bootstrapper : Bootstrapper<RootViewModel>
}
#if !DEBUG
protected override void OnUnhandledException(DispatcherUnhandledExceptionEventArgs e)
protected override void OnUnhandledException(DispatcherUnhandledExceptionEventArgs args)
{
base.OnUnhandledException(e);
base.OnUnhandledException(args);
MessageBox.Show(
e.Exception.ToString(),
args.Exception.ToString(),
"Error occured",
MessageBoxButton.OK,
MessageBoxImage.Error

View file

@ -38,8 +38,6 @@ public class DashboardViewModel : PropertyChangedBase
public string? Token { get; set; }
public bool IsTokenSet => !string.IsNullOrWhiteSpace(Token);
private IReadOnlyDictionary<Guild, IReadOnlyList<Channel>>? ChannelsByGuild { get; set; }
public IReadOnlyList<Guild>? AvailableGuilds => ChannelsByGuild?.Keys.ToArray();

View file

@ -6,6 +6,7 @@
xmlns:behaviors="clr-namespace:DiscordChatExporter.Gui.Behaviors"
xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
xmlns:components="clr-namespace:DiscordChatExporter.Gui.ViewModels.Components"
xmlns:controls="clr-namespace:DiscordChatExporter.Gui.Views.Controls"
xmlns:converters="clr-namespace:DiscordChatExporter.Gui.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:data="clr-namespace:DiscordChatExporter.Core.Discord.Data;assembly=DiscordChatExporter.Core"
@ -75,38 +76,29 @@
Kind="Key" />
<!-- Token value -->
<TextBox
<controls:RevealablePasswordBox
x:Name="TokenValueTextBox"
Grid.Column="1"
Margin="0,6,6,8"
VerticalAlignment="Bottom"
materialDesign:HintAssist.Hint="Token"
materialDesign:TextFieldAssist.DecorationVisibility="Hidden"
materialDesign:TextFieldAssist.TextBoxViewMargin="0,0,2,0"
BorderThickness="0"
FontFamily="Consolas"
FontSize="16"
Text="{Binding Token, UpdateSourceTrigger=PropertyChanged}">
<TextBox.Style>
<Style BasedOn="{StaticResource {x:Type TextBox}}" TargetType="{x:Type TextBox}">
Password="{Binding Token, UpdateSourceTrigger=PropertyChanged}">
<controls:RevealablePasswordBox.Style>
<Style TargetType="{x:Type controls:RevealablePasswordBox}">
<Style.Triggers>
<!-- Blur the token when it's out of focus -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType=materialDesign:Card}}" Value="False" />
<Condition Binding="{Binding IsFocused, RelativeSource={RelativeSource Self}}" Value="False" />
<!-- Don't blur if the token is not set, so the user can see the hint text -->
<Condition Binding="{Binding IsTokenSet}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Effect">
<Setter.Value>
<BlurEffect Radius="12" />
</Setter.Value>
</Setter>
</MultiDataTrigger>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType=materialDesign:Card}}" Value="True">
<Setter Property="IsRevealed" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource AncestorType=materialDesign:Card}}" Value="True">
<Setter Property="IsRevealed" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</controls:RevealablePasswordBox.Style>
</controls:RevealablePasswordBox>
<!-- Pull data button -->
<Button

View file

@ -0,0 +1,24 @@
<UserControl
x:Class="DiscordChatExporter.Gui.Views.Controls.RevealablePasswordBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:s="https://github.com/canton7/Stylet"
x:Name="Root"
mc:Ignorable="d">
<Grid>
<TextBox
materialDesign:TextFieldAssist.DecorationVisibility="Hidden"
BorderThickness="{Binding BorderThickness, ElementName=Root}"
Text="{Binding Password, ElementName=Root}"
Visibility="{Binding IsRevealed, ElementName=Root, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" />
<PasswordBox
x:Name="PasswordBox"
materialDesign:TextFieldAssist.DecorationVisibility="Hidden"
BorderThickness="{Binding BorderThickness, ElementName=Root}"
PasswordChanged="PasswordBox_OnPasswordChanged"
Visibility="{Binding IsRevealed, ElementName=Root, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}}" />
</Grid>
</UserControl>

View file

@ -0,0 +1,50 @@
using System.Windows;
namespace DiscordChatExporter.Gui.Views.Controls;
public partial class RevealablePasswordBox
{
public static readonly DependencyProperty PasswordProperty = DependencyProperty.Register(
nameof(Password),
typeof(string),
typeof(RevealablePasswordBox),
new FrameworkPropertyMetadata(
string.Empty,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
(sender, args) =>
{
var revealablePasswordBox = (RevealablePasswordBox)sender;
var password = (string)args.NewValue;
revealablePasswordBox.PasswordBox.Password = password;
}
)
);
public static readonly DependencyProperty IsRevealedProperty = DependencyProperty.Register(
nameof(IsRevealed),
typeof(bool),
typeof(RevealablePasswordBox),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.None)
);
public string Password
{
get => (string)GetValue(PasswordProperty);
set => SetValue(PasswordProperty, value);
}
public bool IsRevealed
{
get => (bool)GetValue(IsRevealedProperty);
set => SetValue(IsRevealedProperty, value);
}
public RevealablePasswordBox()
{
InitializeComponent();
}
private void PasswordBox_OnPasswordChanged(object sender, RoutedEventArgs args) =>
Password = PasswordBox.Password;
}

View file

@ -60,10 +60,10 @@
<ToggleButton
x:Name="DarkModeToggleButton"
VerticalAlignment="Center"
Checked="DarkModeToggleButton_Checked"
Checked="DarkModeToggleButton_OnChecked"
DockPanel.Dock="Right"
IsChecked="{Binding IsDarkModeEnabled}"
Unchecked="DarkModeToggleButton_Unchecked" />
Unchecked="DarkModeToggleButton_OnUnchecked" />
</DockPanel>
<!-- Persist token -->

View file

@ -9,9 +9,9 @@ public partial class SettingsView
InitializeComponent();
}
private void DarkModeToggleButton_Checked(object sender, RoutedEventArgs e) =>
private void DarkModeToggleButton_OnChecked(object sender, RoutedEventArgs args) =>
App.SetDarkTheme();
private void DarkModeToggleButton_Unchecked(object sender, RoutedEventArgs e) =>
private void DarkModeToggleButton_OnUnchecked(object sender, RoutedEventArgs args) =>
App.SetLightTheme();
}