[GUI] Add dark theme (#388)

pull/403/head
Andrew Kolos 4 years ago committed by GitHub
parent 08442f21b7
commit 19f678ca01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -14,69 +14,13 @@
<!-- Merged dictionaries -->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
<materialDesign:BundledTheme
BaseTheme="Light"
PrimaryColor="Blue"
SecondaryColor="Blue" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- Colors -->
<Color x:Key="PrimaryColor">#343838</Color>
<Color x:Key="PrimaryLightColor">#5E6262</Color>
<Color x:Key="PrimaryDarkColor">#0D1212</Color>
<Color x:Key="AccentColor">#F9A825</Color>
<Color x:Key="AccentDarkColor">#C17900</Color>
<Color x:Key="TextColor">#000000</Color>
<Color x:Key="InverseTextColor">#FFFFFF</Color>
<SolidColorBrush x:Key="PrimaryHueLightBrush" Color="{DynamicResource PrimaryLightColor}" />
<SolidColorBrush x:Key="PrimaryHueLightForegroundBrush" Color="{DynamicResource InverseTextColor}" />
<SolidColorBrush x:Key="PrimaryHueMidBrush" Color="{DynamicResource PrimaryColor}" />
<SolidColorBrush x:Key="PrimaryHueMidForegroundBrush" Color="{DynamicResource InverseTextColor}" />
<SolidColorBrush x:Key="PrimaryHueDarkBrush" Color="{DynamicResource PrimaryDarkColor}" />
<SolidColorBrush x:Key="PrimaryHueDarkForegroundBrush" Color="{DynamicResource InverseTextColor}" />
<SolidColorBrush x:Key="SecondaryAccentBrush" Color="{DynamicResource AccentColor}" />
<SolidColorBrush x:Key="SecondaryAccentForegroundBrush" Color="{DynamicResource TextColor}" />
<SolidColorBrush
x:Key="PrimaryTextBrush"
Opacity="0.87"
Color="{DynamicResource TextColor}" />
<SolidColorBrush
x:Key="SecondaryTextBrush"
Opacity="0.64"
Color="{DynamicResource TextColor}" />
<SolidColorBrush
x:Key="DimTextBrush"
Opacity="0.45"
Color="{DynamicResource TextColor}" />
<SolidColorBrush
x:Key="PrimaryInverseTextBrush"
Opacity="1"
Color="{DynamicResource InverseTextColor}" />
<SolidColorBrush
x:Key="SecondaryInverseTextBrush"
Opacity="0.7"
Color="{DynamicResource InverseTextColor}" />
<SolidColorBrush
x:Key="DimInverseTextBrush"
Opacity="0.52"
Color="{DynamicResource InverseTextColor}" />
<SolidColorBrush
x:Key="AccentTextBrush"
Opacity="1"
Color="{DynamicResource AccentColor}" />
<SolidColorBrush
x:Key="AccentDarkTextBrush"
Opacity="1"
Color="{DynamicResource AccentDarkColor}" />
<SolidColorBrush
x:Key="DividerBrush"
Opacity="0.12"
Color="{DynamicResource TextColor}" />
<SolidColorBrush
x:Key="InverseDividerBrush"
Opacity="0.12"
Color="{DynamicResource InverseTextColor}" />
<!-- Styles -->
<Style x:Key="MaterialDesignRoot" TargetType="{x:Type Control}">
<Setter Property="FontFamily" Value="{DynamicResource MaterialDesignFont}" />
@ -84,7 +28,7 @@
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="TextElement.FontSize" Value="13" />
<Setter Property="TextElement.FontWeight" Value="Regular" />
<Setter Property="TextElement.Foreground" Value="{DynamicResource SecondaryTextBrush}" />
<Setter Property="TextElement.Foreground" Value="{DynamicResource MaterialDesignBody}" />
<Setter Property="TextOptions.TextFormattingMode" Value="Ideal" />
<Setter Property="TextOptions.TextRenderingMode" Value="Auto" />
<Setter Property="UseLayoutRounding" Value="True" />
@ -94,27 +38,20 @@
<Style BasedOn="{StaticResource MaterialDesignLinearProgressBar}" TargetType="{x:Type ProgressBar}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource SecondaryAccentBrush}" />
<Setter Property="Height" Value="2" />
<Setter Property="Maximum" Value="1" />
<Setter Property="Minimum" Value="0" />
</Style>
<Style BasedOn="{StaticResource MaterialDesignTextBox}" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}" />
</Style>
<Style BasedOn="{StaticResource MaterialDesignTextBox}" TargetType="{x:Type TextBox}" />
<Style BasedOn="{StaticResource MaterialDesignComboBox}" TargetType="{x:Type ComboBox}">
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}" />
</Style>
<Style BasedOn="{StaticResource MaterialDesignComboBox}" TargetType="{x:Type ComboBox}" />
<Style BasedOn="{StaticResource MaterialDesignDatePicker}" TargetType="{x:Type DatePicker}">
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}" />
</Style>
<Style BasedOn="{StaticResource MaterialDesignDatePicker}" TargetType="{x:Type DatePicker}" />
<Style BasedOn="{StaticResource MaterialDesignTimePicker}" TargetType="{x:Type materialDesign:TimePicker}">
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}" />
</Style>
<Style BasedOn="{StaticResource MaterialDesignTimePicker}" TargetType="{x:Type materialDesign:TimePicker}" />
<Style
x:Key="MaterialDesignFlatDarkButton"

@ -12,6 +12,8 @@ namespace DiscordChatExporter.Gui.Services
public bool IsTokenPersisted { get; set; } = true;
public bool IsDarkThemeEnabled { get; set; } = false;
public int ParallelLimit { get; set; } = 1;
public AuthToken? LastToken { get; set; }

@ -0,0 +1,42 @@
using MaterialDesignThemes.Wpf;
using System.Windows.Media;
namespace DiscordChatExporter.Gui
{
public sealed class Theme
{
public static Theme Light { get; } = new Theme(new MaterialDesignLightTheme(), HexToColor.Convert("#343838"), HexToColor.Convert("#F9A825"));
public static Theme Dark { get; } = new Theme(new MaterialDesignDarkTheme(), HexToColor.Convert("#E8E8E8"), HexToColor.Convert("#F9A825"));
public static void SetCurrent(Theme theme)
{
var paletteHelper = new PaletteHelper();
var materialTheme = paletteHelper.GetTheme();
materialTheme.SetBaseTheme(theme.BaseTheme);
materialTheme.SetPrimaryColor(theme.PrimaryColor);
materialTheme.SetSecondaryColor(theme.SecondaryColor);
paletteHelper.SetTheme(materialTheme);
}
public Theme(IBaseTheme baseTheme, Color primaryColor, Color secondaryColor)
{
BaseTheme = baseTheme;
PrimaryColor = primaryColor;
SecondaryColor = secondaryColor;
}
public IBaseTheme BaseTheme { get; }
public Color PrimaryColor { get; }
public Color SecondaryColor { get; }
class HexToColor
{
public static Color Convert(string hex)
{
return (Color)ColorConverter.ConvertFromString(hex);
}
}
}
}

@ -26,6 +26,12 @@ namespace DiscordChatExporter.Gui.ViewModels.Dialogs
set => _settingsService.IsTokenPersisted = value;
}
public bool IsDarkThemeEnabled
{
get => _settingsService.IsDarkThemeEnabled;
set => _settingsService.IsDarkThemeEnabled = value;
}
public int ParallelLimit
{
get => _settingsService.ParallelLimit;

@ -107,6 +107,8 @@ namespace DiscordChatExporter.Gui.ViewModels
IsBotToken = _settingsService.LastToken.Type == AuthTokenType.Bot;
TokenValue = _settingsService.LastToken.Value;
}
Theme.SetCurrent(_settingsService.IsDarkThemeEnabled ? Theme.Dark : Theme.Light);
await HandleAutoUpdateAsync();
}

@ -48,12 +48,13 @@
Margin="8,0,0,0"
VerticalAlignment="Center"
FontSize="19"
FontWeight="Light"
TextTrimming="CharacterEllipsis"
Visibility="{Binding IsSingleChannel, Converter={x:Static s:BoolToVisibilityConverter.Instance}}">
<Run Text="{Binding Channels[0].Category, Mode=OneWay}" ToolTip="{Binding Channels[0].Category, Mode=OneWay}" />
<Run Text="/" />
<Run
Foreground="{DynamicResource PrimaryTextBrush}"
FontWeight="DemiBold"
Text="{Binding Channels[0].Name, Mode=OneWay}"
ToolTip="{Binding Channels[0].Name, Mode=OneWay}" />
</TextBlock>
@ -163,18 +164,13 @@
<ToggleButton
x:Name="AdvancedSectionToggleButton"
Grid.Column="0"
Margin="8"
Width="24"
Height="24"
Margin="12"
Cursor="Hand"
Loaded="AdvancedSectionToggleButton_OnLoaded"
Style="{DynamicResource MaterialDesignFlatToggleButton}"
ToolTip="Show advanced options">
<ToggleButton.Content>
<materialDesign:PackIcon
Width="24"
Height="24"
Kind="Menu" />
</ToggleButton.Content>
</ToggleButton>
Style="{DynamicResource MaterialDesignHamburgerToggleButton}"
ToolTip="Show advanced options" />
<Button
Grid.Column="2"

@ -15,7 +15,6 @@
<TextBlock
Margin="16"
FontSize="17"
Foreground="{DynamicResource PrimaryTextBrush}"
Text="Settings" />
<!-- Date format -->
@ -56,11 +55,28 @@
IsChecked="{Binding IsTokenPersisted}" />
</DockPanel>
<!-- Dark/Light theme -->
<DockPanel
Background="Transparent"
LastChildFill="False"
ToolTip="Persist last used token between sessions">
<TextBlock
Margin="16,8"
DockPanel.Dock="Left"
Text="Dark theme" />
<ToggleButton
Margin="16,8"
Checked="ToggleButton_Checked"
DockPanel.Dock="Right"
IsChecked="{Binding IsDarkThemeEnabled}"
Unchecked="ToggleButton_Unchecked" />
</DockPanel>
<!-- Parallel limit -->
<StackPanel Background="Transparent" ToolTip="How many channels can be exported at the same time">
<TextBlock Margin="16,8">
<Run Text="Parallel limit:" />
<Run Foreground="{DynamicResource PrimaryTextBrush}" Text="{Binding ParallelLimit, Mode=OneWay}" />
<Run Text="{Binding ParallelLimit, Mode=OneWay}" />
</TextBlock>
<Slider
Margin="16,8"

@ -1,4 +1,8 @@
namespace DiscordChatExporter.Gui.Views.Dialogs
using MaterialDesignThemes;
using MaterialDesignThemes.Wpf;
using System.Windows.Media.Media3D;
namespace DiscordChatExporter.Gui.Views.Dialogs
{
public partial class SettingsView
{
@ -6,5 +10,20 @@
{
InitializeComponent();
}
private void ToggleButton_Checked(object sender, System.Windows.RoutedEventArgs e)
{
setBaseTheme(Theme.Dark);
}
private void ToggleButton_Unchecked(object sender, System.Windows.RoutedEventArgs e)
{
setBaseTheme(Theme.Light);
}
private void setBaseTheme(Theme theme)
{
Theme.SetCurrent(theme);
}
}
}

@ -46,10 +46,7 @@
</Grid.RowDefinitions>
<!-- Toolbar -->
<Grid
Grid.Row="0"
Background="{DynamicResource PrimaryHueMidBrush}"
TextElement.Foreground="{DynamicResource SecondaryInverseTextBrush}">
<Grid Grid.Row="0" Background="{DynamicResource MaterialDesignDarkBackground}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
@ -124,8 +121,12 @@
Margin="6"
Padding="4"
Command="{s:Action ShowSettings}"
Style="{DynamicResource MaterialDesignFlatDarkButton}"
Foreground="{DynamicResource MaterialDesignDarkForeground}"
Style="{DynamicResource MaterialDesignFlatButton}"
ToolTip="Settings">
<Button.Resources>
<SolidColorBrush x:Key="MaterialDesignFlatButtonClick" Color="#4C4C4C" />
</Button.Resources>
<materialDesign:PackIcon
Width="24"
Height="24"
@ -136,12 +137,17 @@
<!-- Progress bar -->
<ProgressBar
Grid.Row="1"
Background="{DynamicResource PrimaryHueMidBrush}"
Background="{DynamicResource MaterialDesignDarkBackground}"
IsIndeterminate="{Binding IsProgressIndeterminate}"
Value="{Binding ProgressManager.Progress, Mode=OneWay}" />
<!-- Content -->
<Grid Grid.Row="2" IsEnabled="{Binding IsBusy, Converter={x:Static converters:InverseBoolConverter.Instance}}">
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontWeight" Value="Light" />
</Style>
</Grid.Resources>
<!-- Placeholder / usage instructions -->
<Grid Margin="32,32,8,8" Visibility="{Binding AvailableGuilds, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}}">
<!-- For user token -->
@ -151,25 +157,25 @@
<Run Text="1. Open Discord" />
<LineBreak />
<Run Text="2. Press" />
<Run Foreground="{DynamicResource PrimaryTextBrush}" Text="Ctrl+Shift+I" />
<Run FontWeight="Bold" Text="Ctrl+Shift+I" />
<Run Text="to show developer tools" />
<LineBreak />
<Run Text="3. Navigate to the" />
<Run Foreground="{DynamicResource PrimaryTextBrush}" Text="Application" />
<Run FontWeight="Bold" Text="Application" />
<Run Text="tab" />
<LineBreak />
<Run Text="4. Select" />
<Run Foreground="{DynamicResource PrimaryTextBrush}" Text="Local Storage" />
<Run FontWeight="Bold" Text="Local Storage" />
<Run Text="&gt;" />
<Run Foreground="{DynamicResource PrimaryTextBrush}" Text="https://discord.com" />
<Run FontWeight="Bold" Text="https://discord.com" />
<Run Text="on the left" />
<LineBreak />
<Run Text="5. Press" />
<Run Foreground="{DynamicResource PrimaryTextBrush}" Text="Ctrl+R" />
<Run FontWeight="Bold" Text="Ctrl+R" />
<Run Text="to reload" />
<LineBreak />
<Run Text="6. Find" />
<Run Foreground="{DynamicResource PrimaryTextBrush}" Text="token" />
<Run FontWeight="Bold" Text="token" />
<Run Text="at the bottom and copy the value" />
</TextBlock>
<TextBlock Margin="0,24,0,0" FontSize="14">
@ -177,7 +183,10 @@
<LineBreak />
<Run Text="To authorize using bot token instead, click" />
<InlineUIContainer>
<materialDesign:PackIcon Margin="1,0,0,-3" Kind="Account" />
<materialDesign:PackIcon
Margin="1,0,0,-3"
Foreground="{DynamicResource PrimaryHueMidBrush}"
Kind="Account" />
</InlineUIContainer>
</TextBlock>
<TextBlock Margin="0,24,0,0" FontSize="14">
@ -188,25 +197,34 @@
<!-- For bot token -->
<StackPanel Visibility="{Binding IsBotToken, Converter={x:Static s:BoolToVisibilityConverter.Instance}}">
<TextBlock FontSize="18" Text="Please provide your bot token to authorize" />
<TextBlock Margin="8,8,0,0" FontSize="14">
<TextBlock
FontSize="18"
FontWeight="Light"
Text="Please provide your bot token to authorize" />
<TextBlock
Margin="8,8,0,0"
FontSize="14"
FontWeight="Light">
<Run Text="1. Open Discord developer portal" />
<LineBreak />
<Run Text="2. Open your application's settings" />
<LineBreak />
<Run Text="3. Navigate to the" />
<Run Foreground="{DynamicResource PrimaryTextBrush}" Text="Bot" />
<Run FontWeight="Bold" Text="Bot" />
<Run Text="section on the left" />
<LineBreak />
<Run Text="4. Under" />
<Run Foreground="{DynamicResource PrimaryTextBrush}" Text="Token" />
<Run FontWeight="Bold" Text="Token" />
<Run Text="click" />
<Run Foreground="{DynamicResource PrimaryTextBrush}" Text="Copy" />
<Run FontWeight="Bold" Text="Copy" />
</TextBlock>
<TextBlock Margin="0,24,0,0" FontSize="14">
<Run Text="To authorize using user token instead, click" />
<InlineUIContainer>
<materialDesign:PackIcon Margin="1,0,0,-1" Kind="Robot" />
<materialDesign:PackIcon
Margin="1,0,0,-1"
Foreground="{DynamicResource PrimaryHueMidBrush}"
Kind="Robot" />
</InlineUIContainer>
</TextBlock>
<TextBlock Margin="0,24,0,0" FontSize="14">
@ -226,7 +244,7 @@
<!-- Guilds -->
<Border
Grid.Column="0"
BorderBrush="{DynamicResource DividerBrush}"
BorderBrush="{DynamicResource MaterialDesignDivider}"
BorderThickness="0,0,1,0">
<ListBox
ItemsSource="{Binding AvailableGuilds}"
@ -245,7 +263,7 @@
Width="48"
Height="48"
Margin="12,4,12,4"
Fill="{DynamicResource DividerBrush}" />
Fill="{DynamicResource MaterialDesignDivider}" />
<!-- Guild icon -->
<Ellipse
@ -284,7 +302,7 @@
Margin="0"
Padding="0"
Background="Transparent"
BorderBrush="{DynamicResource DividerBrush}"
BorderBrush="{DynamicResource MaterialDesignDivider}"
BorderThickness="0,1,0,0"
Header="{Binding Name}"
IsExpanded="False">
@ -322,7 +340,6 @@
Margin="3,8,8,8"
VerticalAlignment="Center"
FontSize="14"
Foreground="{DynamicResource PrimaryTextBrush}"
Text="{Binding Name, Mode=OneWay}" />
<!-- Is selected checkmark -->

Loading…
Cancel
Save