mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-05-03 19:13:39 +00:00
Add GUI (#7)
* Create a dummy WPF project * Set up Ammy placeholders * Don't track autogenerated files * Basic layout * Add Program.cs * Implement basic workflow * Autofocus token textbox and add Enter key handler * Strip double quotes from token * AmmyUI converters are slightly dumb :( * Use CanExecute * Add file path select and theme select, also refactor * Persist token * Trying to improve UI/UX - 1 * Rename stuff * Finish improving UI/UX * Remove data placeholder * Remove border on middle grid * Ok now i'm done * Improve Discord API layer * Add lots of stuff * Show filesizes in export * Improve export * Animations * Update readme * Improving gui again * Improve UI again * Refactor
This commit is contained in:
261
DiscordChatExporter/Views/MainWindow.ammy
Normal file
261
DiscordChatExporter/Views/MainWindow.ammy
Normal file
@@ -0,0 +1,261 @@
|
||||
using MaterialDesignThemes.Wpf
|
||||
using MaterialDesignThemes.Wpf.Transitions
|
||||
|
||||
Window "DiscordChatExporter.Views.MainWindow" {
|
||||
Title: "DiscordChatExporter"
|
||||
Width: 600
|
||||
Height: 550
|
||||
Background: resource dyn "MaterialDesignPaper"
|
||||
DataContext: bind MainViewModel from $resource Locator
|
||||
FocusManager.FocusedElement: bind from "TokenTextBox"
|
||||
FontFamily: resource dyn "MaterialDesignFont"
|
||||
SnapsToDevicePixels: true
|
||||
TextElement.FontSize: 13
|
||||
TextElement.FontWeight: Regular
|
||||
TextElement.Foreground: resource dyn "SecondaryTextBrush"
|
||||
TextOptions.TextFormattingMode: Ideal
|
||||
TextOptions.TextRenderingMode: Auto
|
||||
UseLayoutRounding: true
|
||||
WindowStartupLocation: CenterScreen
|
||||
|
||||
DialogHost {
|
||||
DockPanel {
|
||||
IsEnabled: bind IsBusy
|
||||
convert (bool b) => b ? false : true
|
||||
|
||||
// Toolbar
|
||||
Border {
|
||||
DockPanel.Dock: Top
|
||||
Background: resource dyn "PrimaryHueMidBrush"
|
||||
TextElement.Foreground: resource dyn "SecondaryInverseTextBrush"
|
||||
StackPanel {
|
||||
Grid {
|
||||
#TwoColumns("*", "Auto")
|
||||
|
||||
Card {
|
||||
Grid.Column: 0
|
||||
Margin: "6 6 0 6"
|
||||
|
||||
Grid {
|
||||
#TwoColumns("*", "Auto")
|
||||
|
||||
// Token
|
||||
TextBox "TokenTextBox" {
|
||||
Grid.Column: 0
|
||||
Margin: 6
|
||||
BorderThickness: 0
|
||||
HintAssist.Hint: "Token"
|
||||
KeyDown: TokenTextBox_KeyDown
|
||||
FontSize: 16
|
||||
Text: bind Token
|
||||
set [ UpdateSourceTrigger: PropertyChanged ]
|
||||
}
|
||||
|
||||
// Submit
|
||||
Button {
|
||||
Grid.Column: 1
|
||||
Margin: "0 6 6 6"
|
||||
Padding: 4
|
||||
Command: bind PullDataCommand
|
||||
Style: resource dyn "MaterialDesignFlatButton"
|
||||
|
||||
PackIcon {
|
||||
Width: 24
|
||||
Height: 24
|
||||
Kind: PackIconKind.ArrowRight
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Popup menu
|
||||
PopupBox {
|
||||
Grid.Column: 1
|
||||
Foreground: resource dyn "PrimaryHueMidForegroundBrush"
|
||||
PlacementMode: LeftAndAlignTopEdges
|
||||
|
||||
StackPanel {
|
||||
Button {
|
||||
Command: bind ShowSettingsCommand
|
||||
Content: "Settings"
|
||||
}
|
||||
Button {
|
||||
Command: bind ShowAboutCommand
|
||||
Content: "About"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Progress
|
||||
ProgressBar {
|
||||
Background: Transparent
|
||||
IsIndeterminate: true
|
||||
Visibility: bind IsBusy
|
||||
convert (bool b) => b ? Visibility.Visible : Visibility.Hidden
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Content
|
||||
Grid {
|
||||
DockPanel {
|
||||
Background: resource dyn "MaterialDesignCardBackground"
|
||||
Visibility: bind IsDataAvailable
|
||||
convert (bool b) => b ? Visibility.Visible : Visibility.Hidden
|
||||
|
||||
// Guilds
|
||||
Border {
|
||||
DockPanel.Dock: Left
|
||||
BorderBrush: resource dyn "DividerBrush"
|
||||
BorderThickness: "0 0 1 0"
|
||||
|
||||
ListBox {
|
||||
ItemsSource: bind AvailableGuilds
|
||||
ScrollViewer.VerticalScrollBarVisibility: Hidden
|
||||
SelectedItem: bind SelectedGuild
|
||||
VirtualizingStackPanel.IsVirtualizing: false
|
||||
|
||||
ItemTemplate: DataTemplate {
|
||||
TransitioningContent {
|
||||
OpeningEffect: TransitionEffect {
|
||||
Duration: "0:0:0.3"
|
||||
Kind: SlideInFromRight
|
||||
}
|
||||
|
||||
Border {
|
||||
Margin: -8
|
||||
Background: Transparent
|
||||
Cursor: CursorType.Hand
|
||||
|
||||
Image {
|
||||
Margin: 6
|
||||
Width: 48
|
||||
Height: 48
|
||||
Source: bind IconUrl
|
||||
ToolTip: bind Name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Channels
|
||||
Border {
|
||||
ListBox {
|
||||
ItemsSource: bind AvailableChannels
|
||||
HorizontalContentAlignment: Stretch
|
||||
VirtualizingStackPanel.IsVirtualizing: false
|
||||
|
||||
ItemTemplate: DataTemplate {
|
||||
TransitioningContent {
|
||||
OpeningEffect: TransitionEffect {
|
||||
Duration: "0:0:0.3"
|
||||
Kind: SlideInFromLeft
|
||||
}
|
||||
|
||||
@StackPanelHorizontal {
|
||||
Margin: -8
|
||||
Background: Transparent
|
||||
Cursor: CursorType.Hand
|
||||
InputBindings: [
|
||||
MouseBinding {
|
||||
Command: bind DataContext.ExportChannelCommand from $ancestor<ItemsControl>
|
||||
CommandParameter: bind
|
||||
MouseAction: LeftClick
|
||||
}
|
||||
]
|
||||
|
||||
PackIcon {
|
||||
Margin: "4 7 0 6"
|
||||
Kind: PackIconKind.Pound
|
||||
VerticalAlignment: Center
|
||||
}
|
||||
TextBlock {
|
||||
Margin: "3 6 6 6"
|
||||
FontSize: 14
|
||||
Text: bind Name
|
||||
VerticalAlignment: Center
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Content placeholder
|
||||
StackPanel {
|
||||
Margin: "32 32 8 8"
|
||||
Visibility: bind IsDataAvailable
|
||||
convert (bool b) => b ? Visibility.Hidden : Visibility.Visible
|
||||
|
||||
TextBlock {
|
||||
FontSize: 18
|
||||
Text: "DiscordChatExporter needs your authorization token to work."
|
||||
}
|
||||
|
||||
TextBlock {
|
||||
Margin: "0 8 0 0"
|
||||
FontSize: 16
|
||||
Text: "To obtain it, follow these steps:"
|
||||
}
|
||||
|
||||
TextBlock {
|
||||
Margin: "8 0 0 0"
|
||||
FontSize: 14
|
||||
|
||||
Run {
|
||||
Text: "1. Open the Discord app"
|
||||
}
|
||||
LineBreak { }
|
||||
Run {
|
||||
Text: "2. Log in if you haven't"
|
||||
}
|
||||
LineBreak { }
|
||||
Run {
|
||||
Text: "3. Press"
|
||||
}
|
||||
Run {
|
||||
Text: "Ctrl+Shift+I"
|
||||
Foreground: resource dyn "PrimaryTextBrush"
|
||||
}
|
||||
LineBreak { }
|
||||
Run {
|
||||
Text: "4. Navigate to"
|
||||
}
|
||||
Run {
|
||||
Text: "Application"
|
||||
Foreground: resource dyn "PrimaryTextBrush"
|
||||
}
|
||||
Run { Text: "tab" }
|
||||
LineBreak { }
|
||||
Run {
|
||||
Text: "5. Expand"
|
||||
}
|
||||
Run {
|
||||
Text: "Storage > Local Storage > https://discordapp.com"
|
||||
Foreground: resource dyn "PrimaryTextBrush"
|
||||
}
|
||||
LineBreak { }
|
||||
Run {
|
||||
Text: "6. Find"
|
||||
}
|
||||
Run {
|
||||
Text: ""token""
|
||||
Foreground: resource dyn "PrimaryTextBrush"
|
||||
}
|
||||
Run {
|
||||
Text: "under key and copy the value"
|
||||
}
|
||||
LineBreak { }
|
||||
Run {
|
||||
Text: "7. Paste the value in the textbox above"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
DiscordChatExporter/Views/MainWindow.ammy.cs
Normal file
32
DiscordChatExporter/Views/MainWindow.ammy.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System.Reflection;
|
||||
using System.Windows.Input;
|
||||
using DiscordChatExporter.Messages;
|
||||
using DiscordChatExporter.ViewModels;
|
||||
using GalaSoft.MvvmLight.Messaging;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using Tyrrrz.Extensions;
|
||||
|
||||
namespace DiscordChatExporter.Views
|
||||
{
|
||||
public partial class MainWindow
|
||||
{
|
||||
private IMainViewModel ViewModel => (IMainViewModel) DataContext;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
Title += $" v{Assembly.GetExecutingAssembly().GetName().Version}";
|
||||
|
||||
Messenger.Default.Register<ShowSettingsMessage>(this, m => DialogHost.Show(new SettingsDialog()).Forget());
|
||||
}
|
||||
|
||||
public void TokenTextBox_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
// Execute command
|
||||
ViewModel.PullDataCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
26
DiscordChatExporter/Views/SettingsDialog.ammy
Normal file
26
DiscordChatExporter/Views/SettingsDialog.ammy
Normal file
@@ -0,0 +1,26 @@
|
||||
using MaterialDesignThemes.Wpf
|
||||
|
||||
UserControl "DiscordChatExporter.Views.SettingsDialog" {
|
||||
DataContext: bind SettingsViewModel from $resource Locator
|
||||
Width: 250
|
||||
|
||||
StackPanel {
|
||||
// Theme
|
||||
ComboBox {
|
||||
HintAssist.Hint: "Theme"
|
||||
HintAssist.IsFloating: true
|
||||
Margin: 8
|
||||
IsReadOnly: true
|
||||
ItemsSource: bind AvailableThemes
|
||||
SelectedItem: bind Theme
|
||||
}
|
||||
|
||||
// Save
|
||||
Button {
|
||||
Command: DialogHost.CloseDialogCommand
|
||||
Content: "SAVE"
|
||||
Margin: 8
|
||||
Style: resource dyn "MaterialDesignFlatButton"
|
||||
}
|
||||
}
|
||||
}
|
||||
10
DiscordChatExporter/Views/SettingsDialog.ammy.cs
Normal file
10
DiscordChatExporter/Views/SettingsDialog.ammy.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace DiscordChatExporter.Views
|
||||
{
|
||||
public partial class SettingsDialog
|
||||
{
|
||||
public SettingsDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user