mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-07-11 16:31:57 +02:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b7548756a8 | |||
| 8f9c0f8660 | |||
| b12be796c7 | |||
| 7a69c87b56 | |||
| 9e7ad4d85c | |||
| 0fb4bea64d | |||
| d8abd011e5 | |||
| 9a5697b5b5 | |||
| 886b8442d3 | |||
| bedf7de8c6 | |||
| 5ef329b63c | |||
| 060e55a0d7 | |||
| 61444aad30 | |||
| 9b3421e8a5 |
@@ -1,51 +0,0 @@
|
||||
# Install .NET runtime
|
||||
|
||||
**.NET 8.0 Runtime** is required by **DiscordChatExporter**.
|
||||
|
||||
> **Note**:
|
||||
> Installing the **.NET Runtime** is not required if you running **DiscordChatExporter** using [Docker](Docker.md).
|
||||
|
||||
## Windows
|
||||
|
||||
Both the GUI and the CLI flavors of **DiscordChatExporter** for Windows come with a bootstrapper that should automatically install all the required prerequisites. Simply run the application and follow the presented instructions.
|
||||
|
||||
If, for some reason, you need to install the runtime manually, use one of the download links below:
|
||||
|
||||
- [.NET 8.0 Runtime for **Windows x64**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.0-windows-x86-installer)
|
||||
- [.NET 8.0 Runtime for **Windows x86**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.0-windows-x64-installer)
|
||||
- [.NET 8.0 Runtime for **Windows arm64**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.0-windows-arm64-installer)
|
||||
|
||||
> **Note**:
|
||||
> [How can I tell if my computer is running a 32-bit (x86) or a 64-bit (x64) version of Windows?](https://support.microsoft.com/help/15056/windows-32-64-bit-faq)
|
||||
|
||||
## macOS
|
||||
|
||||
Use one of the download links below:
|
||||
|
||||
- [.NET 8.0 Runtime for **macOS x64**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.0-macos-x64-installer)
|
||||
- [.NET 8.0 Runtime for **macOS arm64**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.0-macos-arm64-installer)
|
||||
|
||||
> **Note**:
|
||||
> [Is my Mac using an Intel processor (x64) or Apple Silicon (arm64)?](https://support.apple.com/HT211814)
|
||||
|
||||
## Linux
|
||||
|
||||
Installing the .NET Runtime works differently depending on which Linux distribution you use. Check out the instructions for your distro:
|
||||
|
||||
- [Ubuntu](https://docs.microsoft.com/dotnet/core/install/linux-ubuntu)
|
||||
- [Debian](https://docs.microsoft.com/dotnet/core/install/linux-debian)
|
||||
- [Fedora](https://docs.microsoft.com/dotnet/core/install/linux-fedora)
|
||||
|
||||
For other distros, please check the _'Install on Linux'_ menu on the left of [this page](https://docs.microsoft.com/dotnet/core/install/linux).
|
||||
|
||||
## Verify installation (optional)
|
||||
|
||||
You can check which version of **.NET Runtime** is installed by running the following command in a terminal:
|
||||
|
||||
```console
|
||||
$ dotnet --info
|
||||
|
||||
.NET runtimes installed:
|
||||
Microsoft.NETCore.App 7.0.x [C:\path\to\dotnet\shared\Microsoft.NETCore.App]
|
||||
Microsoft.WindowsDesktop.App 7.0.x [C:\path\to\dotnet\shared\Microsoft.WindowsDesktop.App]
|
||||
```
|
||||
@@ -35,13 +35,13 @@ You can open `.html` files with a web browser, such as Google Chrome.
|
||||
|
||||
> **Warning**:
|
||||
> If a picture is deleted, or if a user changes its avatar, the respective images will no longer be displayed.
|
||||
> Export using the "Download referenced assets" (`--media`) option to avoid this.
|
||||
> Export using the "Download assets" (`--media`) option to avoid this.
|
||||
|
||||
### Plain Text
|
||||
|
||||
<img src="https://i.imgur.com/PbUyRXD.png" height="400"/>
|
||||
|
||||
The Plain Text format is the best option for archiving due to its small size.
|
||||
The Plain Text format formats messages as plain text, and has the smallest size.
|
||||
You can open `.txt` files with a text editor, such as Notepad.
|
||||
|
||||
### JSON
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
## Installation & Usage
|
||||
|
||||
- [Get .NET Runtime](Dotnet.md)
|
||||
- Getting started:
|
||||
- [Using the GUI](Using-the-GUI.md)
|
||||
- [Using the CLI](Using-the-CLI.md)
|
||||
@@ -28,6 +27,5 @@
|
||||
- [General questions](Troubleshooting.md#general)
|
||||
- [First steps help](Troubleshooting.md#first-steps)
|
||||
- [It's crashing/failing](Troubleshooting.md#DCE-is-crashingfailing)
|
||||
- [.NET Core Runtime is required](Troubleshooting.md#net-core-runtime-is-required)
|
||||
- [Errors](Troubleshooting.md#errors)
|
||||
- [**More help**](Troubleshooting.md)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
# Scheduling exports with Cron
|
||||
|
||||
Make sure you already have **DiscordChatExporter.CLI** downloaded and **.NET Runtime** installed.
|
||||
|
||||
## Creating the script
|
||||
|
||||
1. Open Terminal and create a new text file with `nano /path/to/DiscordChatExporter/cron.sh`
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
# Scheduling exports on macOS
|
||||
|
||||
Make sure you already have **DiscordChatExporter.CLI** downloaded and **.NET Runtime** installed.
|
||||
|
||||
## Creating the script
|
||||
|
||||
1. Open TextEdit.app and create a new file
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
# Scheduling exports on Windows
|
||||
|
||||
We'll be using [DiscordChatExporter CLI](https://github.com/Tyrrrz/DiscordChatExporter/releases/latest), PowerShell, and Task Scheduler.
|
||||
Make sure you already have **DiscordChatExporter.CLI** downloaded and **.NET Runtime** installed.
|
||||
|
||||
## Creating the script
|
||||
|
||||
1. Open a text editor such as Notepad and paste:
|
||||
|
||||
@@ -70,7 +70,7 @@ Check the following page: [Obtaining token](Token-and-IDs.md)
|
||||
|
||||
### When I open DCE a black window pops up quickly or nothing shows up
|
||||
|
||||
If you have [.NET Runtime correctly installed](Dotnet.md), you might have downloaded the CLI flavor, try [downloading the GUI](Getting-started.md#gui-or-cli) instead.
|
||||
You might have downloaded the CLI flavor of the app, which is meant to be run in a terminal. Try [downloading the GUI](Getting-started.md#gui-or-cli) instead if that's what you want.
|
||||
|
||||
### How can I set DCE to export automatically at certain times?
|
||||
|
||||
@@ -84,16 +84,6 @@ Check the following pages to learn how to schedule **DiscordChatExporter.CLI** r
|
||||
|
||||
Try opening it with a different program, try partitioning or use a different file format, like `PlainText`.
|
||||
|
||||
### DCE is crashing/failing
|
||||
|
||||
Check the following page: [Installing .NET Core Runtime](Dotnet.md)
|
||||
|
||||
If you already have .NET Core installed, please check if your problem is a [known issue](https://github.com/Tyrrrz/DiscordChatExporter/issues?q=is%3Aissue) before [opening a bug report](https://github.com/Tyrrrz/DiscordChatExporter/issues/new).
|
||||
|
||||
### .NET Core Runtime is required
|
||||
|
||||
Check the following page: [Installing .NET Core Runtime](Dotnet.md)
|
||||
|
||||
### I see messages in the export, but they have no content
|
||||
|
||||
Your bot is missing the 'Message Content Intent'. Go to the [Discord Developer Portal](https://discord.com/developers/applications), navigate to the 'Bot' section and enable it.
|
||||
|
||||
+3
-10
@@ -1,24 +1,17 @@
|
||||
# Using the CLI
|
||||
|
||||
## Guide
|
||||
|
||||
> **Note**:
|
||||
> Make sure you have [.NET Core installed](Dotnet.md) before attempting to run the commands below.
|
||||
> **Docker** users, please refer to the [Docker usage instructions](Docker.md).
|
||||
|
||||
## Step 1
|
||||
|
||||
After extracting the `.zip`, open Command Prompt, aka `cmd` (`Terminal` on **macOS** and **Linux**).
|
||||
|
||||
## Step 2
|
||||
|
||||
Change the current directory to DCE's folder with `cd C:\path\to\directory`, then press ENTER to run the command.
|
||||
Change the current directory to DCE's folder with `cd C:\path\to\DiscordChatExporter` (`cd /path/to/DiscordChatExporter` on **MacOS** and **Linux**), then press ENTER to run the command.
|
||||
|
||||
**Windows** users can quickly get the directory's path by clicking the address bar while inside the folder.
|
||||
**Windows** users can quickly get the folder's path by clicking the address bar while inside the folder.
|
||||

|
||||
|
||||
**macOS** users can select the `.exe`, hit Command+I (⌘I), and copy what's after `Where:` to get the directory
|
||||

|
||||
**macOS** users can press Command+Option+C (⌘⌥C) while inside the folder (or selecting it) to copy its path to the clipboard.
|
||||
|
||||
You can also drag and drop the folder on **every platform**.
|
||||

|
||||
|
||||
+11
-18
@@ -10,7 +10,7 @@
|
||||
|
||||
### Step 1
|
||||
|
||||
After extracting the `.zip`, open `DiscordChatExporter.exe`
|
||||
After extracting the `.zip`, run `DiscordChatExporter.exe` (Windows), or `DiscordChatExporter` (Mac OS and Linux).
|
||||
|
||||
### Step 2
|
||||
|
||||
@@ -61,37 +61,30 @@ In this screen you can customize the following:
|
||||
|
||||
## Settings
|
||||
|
||||
- **Auto-update**
|
||||
Perform automatic updates on every launch.
|
||||
- **Auto-update** - Perform automatic updates on every launch.
|
||||
Default: Enabled
|
||||
|
||||
> **Note**:
|
||||
> Keep this option enabled to receive the latest features and bug fixes!
|
||||
|
||||
- **Dark mode**
|
||||
Use darker colors in the UI (User Interface).
|
||||
- **Dark mode** - Use darker colors in the UI (User Interface).
|
||||
Default: Disabled
|
||||
|
||||
- **Persist token**
|
||||
Persist last used token between sessions.
|
||||
- **Persist token** - Persist last used token between sessions.
|
||||
Default: Enabled
|
||||
|
||||
- **Show threads**
|
||||
Controls whether threads are shown in the channel list.
|
||||
- **Show threads** - Controls whether threads are shown in the channel list.
|
||||
Default: none
|
||||
|
||||
- **Locale**
|
||||
Customize how dates are formatted in the exported files.
|
||||
- **Locale** - Customize how dates are formatted in the exported files.
|
||||
|
||||
- **Date format**
|
||||
Customize how dates are formatted in the exported files in the settings menu ().
|
||||
- **Date format** - Customize how dates are formatted in the exported files in the settings menu ().
|
||||
|
||||
- **Parallel limit**
|
||||
The number of channels that will be exported at the same time.
|
||||
- **Parallel limit** - The number of channels that will be exported at the same time.
|
||||
Default: 1
|
||||
|
||||
- **Normalize to UTC**
|
||||
Convert all dates to UTC before exporting.
|
||||
|
||||
> **Note**:
|
||||
> Try to keep this number low so that your account doesn't get flagged.
|
||||
|
||||
- **Normalize to UTC** - Convert all dates to UTC before exporting.
|
||||
|
||||
|
||||
@@ -100,6 +100,8 @@ body:
|
||||
required: true
|
||||
- label: I have sponsored this project
|
||||
required: false
|
||||
- label: I have not read any of the above and just checked all the boxes to submit the issue
|
||||
required: false
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
||||
@@ -99,8 +99,7 @@ jobs:
|
||||
# GUI assets aren't suffixed, unlike the CLI assets
|
||||
asset: DiscordChatExporter
|
||||
|
||||
# Need to run on Windows because of DotnetRuntimeBootstrapper's dependency on Ressy
|
||||
runs-on: windows-latest
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
permissions:
|
||||
@@ -124,7 +123,7 @@ jobs:
|
||||
--output ${{ matrix.app }}/bin/publish/
|
||||
--configuration Release
|
||||
--runtime ${{ matrix.rid }}
|
||||
--no-self-contained
|
||||
--self-contained
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
|
||||
@@ -196,7 +195,11 @@ jobs:
|
||||
with:
|
||||
name: ${{ matrix.asset }}.${{ matrix.rid }}
|
||||
path: ${{ matrix.app }}/
|
||||
|
||||
|
||||
- name: Set permissions
|
||||
if: ${{ !startsWith(matrix.rid, 'win') }}
|
||||
run: chmod +x ${{ matrix.app }}/${{ matrix.asset }}
|
||||
|
||||
- name: Create package
|
||||
# Change into the artifacts directory to avoid including the directory itself in the zip archive
|
||||
working-directory: ${{ matrix.app }}/
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
<PackageReference Include="CliFx" Version="2.3.5" />
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.28.2" PrivateAssets="all" />
|
||||
<PackageReference Include="Deorcify" Version="1.0.2" PrivateAssets="all" />
|
||||
<PackageReference Include="DotnetRuntimeBootstrapper" Version="2.5.4" PrivateAssets="all" />
|
||||
<PackageReference Include="Gress" Version="2.1.1" />
|
||||
<PackageReference Include="Spectre.Console" Version="0.49.1" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -676,10 +676,14 @@ public class DiscordClient(string token)
|
||||
.SetQueryParameter("after", currentAfter.ToString())
|
||||
.Build();
|
||||
|
||||
var response = await GetJsonResponseAsync(url, cancellationToken);
|
||||
// Can be null on reactions with an emoji that has been deleted (?)
|
||||
// https://github.com/Tyrrrz/DiscordChatExporter/issues/1226
|
||||
var response = await TryGetJsonResponseAsync(url, cancellationToken);
|
||||
if (response is null)
|
||||
yield break;
|
||||
|
||||
var count = 0;
|
||||
foreach (var userJson in response.EnumerateArray())
|
||||
foreach (var userJson in response.Value.EnumerateArray())
|
||||
{
|
||||
var user = User.Parse(userJson);
|
||||
yield return user;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.28.2" PrivateAssets="all" />
|
||||
<PackageReference Include="Gress" Version="2.1.1" />
|
||||
<PackageReference Include="JsonExtensions" Version="1.2.0" />
|
||||
<PackageReference Include="Polly" Version="8.3.1" />
|
||||
<PackageReference Include="Polly" Version="8.4.0" />
|
||||
<PackageReference Include="RazorBlade" Version="0.6.0" />
|
||||
<PackageReference Include="Superpower" Version="3.0.0" />
|
||||
<PackageReference Include="WebMarkupMin.Core" Version="2.16.0" />
|
||||
|
||||
@@ -7,13 +7,18 @@
|
||||
xmlns:materialAssists="clr-namespace:Material.Styles.Assists;assembly=Material.Styles"
|
||||
xmlns:materialControls="clr-namespace:Material.Styles.Controls;assembly=Material.Styles"
|
||||
xmlns:materialIcons="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:materialStyles="clr-namespace:Material.Styles.Themes;assembly=Material.Styles">
|
||||
xmlns:materialStyles="clr-namespace:Material.Styles.Themes;assembly=Material.Styles"
|
||||
ActualThemeVariantChanged="Application_OnActualThemeVariantChanged">
|
||||
<Application.DataTemplates>
|
||||
<framework:ViewManager />
|
||||
</Application.DataTemplates>
|
||||
|
||||
<Application.Styles>
|
||||
<materialStyles:MaterialTheme />
|
||||
<!-- This theme is used as a stub to pre-load default resources, the actual colors are set through code -->
|
||||
<materialStyles:MaterialTheme
|
||||
BaseTheme="Light"
|
||||
PrimaryColor="Grey"
|
||||
SecondaryColor="DeepOrange" />
|
||||
<materialIcons:MaterialIconStyles />
|
||||
<dialogHostAvalonia:DialogHostStyles />
|
||||
|
||||
@@ -121,7 +126,7 @@
|
||||
|
||||
<!-- Toggle switch -->
|
||||
<Style Selector="ToggleSwitch">
|
||||
<Setter Property="materialAssists:ToggleSwitchAssist.SwitchThumbOffBackground" Value="{DynamicResource MaterialBackgroundBrush}" />
|
||||
<Setter Property="materialAssists:ToggleSwitchAssist.SwitchThumbOffBackground" Value="{DynamicResource ToggleBackgroundBrush}" />
|
||||
</Style>
|
||||
|
||||
<!-- Tooltip -->
|
||||
@@ -132,4 +137,17 @@
|
||||
<Setter Property="TextElement.FontStretch" Value="Normal" />
|
||||
</Style>
|
||||
</Application.Styles>
|
||||
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
<SolidColorBrush x:Key="ToggleBackgroundBrush" Color="#FFFFFF" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<SolidColorBrush x:Key="ToggleBackgroundBrush" Color="#8E8E8E" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -7,6 +7,8 @@ using Avalonia.Media;
|
||||
using Avalonia.Platform;
|
||||
using DiscordChatExporter.Gui.Framework;
|
||||
using DiscordChatExporter.Gui.Services;
|
||||
using DiscordChatExporter.Gui.Utils;
|
||||
using DiscordChatExporter.Gui.Utils.Extensions;
|
||||
using DiscordChatExporter.Gui.ViewModels;
|
||||
using DiscordChatExporter.Gui.ViewModels.Components;
|
||||
using DiscordChatExporter.Gui.ViewModels.Dialogs;
|
||||
@@ -16,9 +18,12 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace DiscordChatExporter.Gui;
|
||||
|
||||
public partial class App : Application, IDisposable
|
||||
public class App : Application, IDisposable
|
||||
{
|
||||
private readonly DisposableCollector _eventRoot = new();
|
||||
|
||||
private readonly ServiceProvider _services;
|
||||
private readonly SettingsService _settingsService;
|
||||
private readonly MainViewModel _mainViewModel;
|
||||
|
||||
public App()
|
||||
@@ -43,17 +48,54 @@ public partial class App : Application, IDisposable
|
||||
services.AddTransient<SettingsViewModel>();
|
||||
|
||||
_services = services.BuildServiceProvider(true);
|
||||
_settingsService = _services.GetRequiredService<SettingsService>();
|
||||
_mainViewModel = _services.GetRequiredService<ViewModelManager>().CreateMainViewModel();
|
||||
|
||||
// Re-initialize the theme when the user changes it
|
||||
_eventRoot.Add(
|
||||
_settingsService.WatchProperty(
|
||||
o => o.Theme,
|
||||
() =>
|
||||
{
|
||||
RequestedThemeVariant = _settingsService.Theme switch
|
||||
{
|
||||
ThemeVariant.Light => Avalonia.Styling.ThemeVariant.Light,
|
||||
ThemeVariant.Dark => Avalonia.Styling.ThemeVariant.Dark,
|
||||
_ => Avalonia.Styling.ThemeVariant.Default
|
||||
};
|
||||
|
||||
InitializeTheme();
|
||||
},
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
// Increase maximum concurrent connections
|
||||
ServicePointManager.DefaultConnectionLimit = 20;
|
||||
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void InitializeTheme()
|
||||
{
|
||||
var actualTheme = RequestedThemeVariant?.Key switch
|
||||
{
|
||||
"Light" => PlatformThemeVariant.Light,
|
||||
"Dark" => PlatformThemeVariant.Dark,
|
||||
_ => PlatformSettings?.GetColorValues().ThemeVariant ?? PlatformThemeVariant.Light
|
||||
};
|
||||
|
||||
this.LocateMaterialTheme<MaterialThemeBase>().CurrentTheme =
|
||||
actualTheme == PlatformThemeVariant.Light
|
||||
? Theme.Create(Theme.Light, Color.Parse("#343838"), Color.Parse("#F9A825"))
|
||||
: Theme.Create(Theme.Dark, Color.Parse("#E8E8E8"), Color.Parse("#F9A825"));
|
||||
}
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
@@ -61,50 +103,20 @@ public partial class App : Application, IDisposable
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
|
||||
// Set custom theme colors
|
||||
SetDefaultTheme();
|
||||
// Set up custom theme colors
|
||||
InitializeTheme();
|
||||
|
||||
// Load settings
|
||||
_settingsService.Load();
|
||||
}
|
||||
|
||||
public void Dispose() => _services.Dispose();
|
||||
}
|
||||
private void Application_OnActualThemeVariantChanged(object? sender, EventArgs args) =>
|
||||
// Re-initialize the theme when the system theme changes
|
||||
InitializeTheme();
|
||||
|
||||
public partial class App
|
||||
{
|
||||
public static void SetLightTheme()
|
||||
public void Dispose()
|
||||
{
|
||||
if (Current is null)
|
||||
return;
|
||||
|
||||
Current.LocateMaterialTheme<MaterialThemeBase>().CurrentTheme = Theme.Create(
|
||||
Theme.Light,
|
||||
Color.Parse("#343838"),
|
||||
Color.Parse("#F9A825")
|
||||
);
|
||||
}
|
||||
|
||||
public static void SetDarkTheme()
|
||||
{
|
||||
if (Current is null)
|
||||
return;
|
||||
|
||||
Current.LocateMaterialTheme<MaterialThemeBase>().CurrentTheme = Theme.Create(
|
||||
Theme.Dark,
|
||||
Color.Parse("#E8E8E8"),
|
||||
Color.Parse("#F9A825")
|
||||
);
|
||||
}
|
||||
|
||||
public static void SetDefaultTheme()
|
||||
{
|
||||
if (Current is null)
|
||||
return;
|
||||
|
||||
var isDarkModeEnabledByDefault =
|
||||
Current.PlatformSettings?.GetColorValues().ThemeVariant == PlatformThemeVariant.Dark;
|
||||
|
||||
if (isDarkModeEnabledByDefault)
|
||||
SetDarkTheme();
|
||||
else
|
||||
SetLightTheme();
|
||||
_eventRoot.Dispose();
|
||||
_services.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ public class LocaleToDisplayNameStringConverter : IValueConverter
|
||||
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) =>
|
||||
value is string locale && !string.IsNullOrWhiteSpace(locale)
|
||||
? CultureInfo.GetCultureInfo(locale).DisplayName
|
||||
: "System default";
|
||||
: "System";
|
||||
|
||||
public object ConvertBack(
|
||||
object? value,
|
||||
|
||||
@@ -20,9 +20,8 @@
|
||||
<PackageReference Include="CSharpier.MsBuild" Version="0.28.2" PrivateAssets="all" />
|
||||
<PackageReference Include="Deorcify" Version="1.0.2" PrivateAssets="all" />
|
||||
<PackageReference Include="DialogHost.Avalonia" Version="0.7.7" />
|
||||
<PackageReference Include="DotnetRuntimeBootstrapper" Version="2.5.4" PrivateAssets="all" />
|
||||
<PackageReference Include="Gress" Version="2.1.1" />
|
||||
<PackageReference Include="Material.Avalonia" Version="3.5.0" />
|
||||
<PackageReference Include="Material.Avalonia" Version="3.6.0" />
|
||||
<PackageReference Include="Material.Icons.Avalonia" Version="2.1.9" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||
<PackageReference Include="Onova" Version="2.6.11" />
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace DiscordChatExporter.Gui.Framework;
|
||||
|
||||
public enum ThemeVariant
|
||||
{
|
||||
System,
|
||||
Light,
|
||||
Dark
|
||||
}
|
||||
@@ -17,8 +17,6 @@ public static class Program
|
||||
|
||||
public static string ProjectUrl { get; } = "https://github.com/Tyrrrz/DiscordChatExporter";
|
||||
|
||||
public static string LatestReleaseUrl { get; } = ProjectUrl + "/releases/latest";
|
||||
|
||||
public static string DocumentationUrl { get; } = ProjectUrl + "/tree/master/.docs";
|
||||
|
||||
public static AppBuilder BuildAvaloniaApp() =>
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Avalonia;
|
||||
using Avalonia.Platform;
|
||||
using Cogwheel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using DiscordChatExporter.Core.Exporting;
|
||||
using DiscordChatExporter.Gui.Framework;
|
||||
using DiscordChatExporter.Gui.Models;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace DiscordChatExporter.Gui.Services;
|
||||
|
||||
@@ -18,10 +16,10 @@ public partial class SettingsService()
|
||||
private bool _isUkraineSupportMessageEnabled = true;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isAutoUpdateEnabled = true;
|
||||
private ThemeVariant _theme;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isDarkModeEnabled;
|
||||
private bool _isAutoUpdateEnabled = true;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isTokenPersisted = true;
|
||||
@@ -38,9 +36,6 @@ public partial class SettingsService()
|
||||
[ObservableProperty]
|
||||
private int _parallelLimit = 1;
|
||||
|
||||
[ObservableProperty]
|
||||
private Version? _lastAppVersion;
|
||||
|
||||
[ObservableProperty]
|
||||
private string? _lastToken;
|
||||
|
||||
@@ -65,17 +60,6 @@ public partial class SettingsService()
|
||||
[ObservableProperty]
|
||||
private string? _lastAssetsDirPath;
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
|
||||
// Reset the dark mode setting separately because its default value is evaluated dynamically
|
||||
// and cannot be set by the field initializer.
|
||||
IsDarkModeEnabled =
|
||||
Application.Current?.PlatformSettings?.GetColorValues().ThemeVariant
|
||||
== PlatformThemeVariant.Dark;
|
||||
}
|
||||
|
||||
public override void Save()
|
||||
{
|
||||
// Clear the token if it's not supposed to be persisted
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using DiscordChatExporter.Core.Utils.Extensions;
|
||||
using DiscordChatExporter.Gui.Framework;
|
||||
using DiscordChatExporter.Gui.Models;
|
||||
@@ -23,25 +22,27 @@ public class SettingsViewModel : DialogViewModelBase
|
||||
_eventRoot.Add(_settingsService.WatchAllProperties(OnAllPropertiesChanged));
|
||||
}
|
||||
|
||||
public IReadOnlyList<ThemeVariant> AvailableThemes { get; } = Enum.GetValues<ThemeVariant>();
|
||||
|
||||
public ThemeVariant Theme
|
||||
{
|
||||
get => _settingsService.Theme;
|
||||
set => _settingsService.Theme = value;
|
||||
}
|
||||
|
||||
public bool IsAutoUpdateEnabled
|
||||
{
|
||||
get => _settingsService.IsAutoUpdateEnabled;
|
||||
set => _settingsService.IsAutoUpdateEnabled = value;
|
||||
}
|
||||
|
||||
public bool IsDarkModeEnabled
|
||||
{
|
||||
get => _settingsService.IsDarkModeEnabled;
|
||||
set => _settingsService.IsDarkModeEnabled = value;
|
||||
}
|
||||
|
||||
public bool IsTokenPersisted
|
||||
{
|
||||
get => _settingsService.IsTokenPersisted;
|
||||
set => _settingsService.IsTokenPersisted = value;
|
||||
}
|
||||
|
||||
public IReadOnlyList<ThreadInclusionMode> AvailableThreadInclusions { get; } =
|
||||
public IReadOnlyList<ThreadInclusionMode> AvailableThreadInclusionModes { get; } =
|
||||
Enum.GetValues<ThreadInclusionMode>();
|
||||
|
||||
public ThreadInclusionMode ThreadInclusionMode
|
||||
|
||||
@@ -79,36 +79,8 @@ public partial class MainViewModel(
|
||||
[RelayCommand]
|
||||
private async Task InitializeAsync()
|
||||
{
|
||||
// Reset settings (needed to resolve the default dark mode setting)
|
||||
settingsService.Reset();
|
||||
|
||||
// Load settings
|
||||
settingsService.Load();
|
||||
|
||||
// Set the correct theme
|
||||
if (settingsService.IsDarkModeEnabled)
|
||||
App.SetDarkTheme();
|
||||
else
|
||||
App.SetLightTheme();
|
||||
|
||||
await ShowUkraineSupportMessageAsync();
|
||||
await CheckForUpdatesAsync();
|
||||
|
||||
// App has just been updated, display the changelog
|
||||
if (
|
||||
settingsService.LastAppVersion is not null
|
||||
&& settingsService.LastAppVersion != Program.Version
|
||||
)
|
||||
{
|
||||
snackbarManager.Notify(
|
||||
$"Successfully updated to {Program.Name} v{Program.VersionString}",
|
||||
"WHAT'S NEW",
|
||||
() => ProcessEx.StartShellExecute(Program.LatestReleaseUrl)
|
||||
);
|
||||
|
||||
settingsService.LastAppVersion = Program.Version;
|
||||
settingsService.Save();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
|
||||
@@ -266,7 +266,6 @@
|
||||
<Border Grid.Column="1">
|
||||
<TreeView
|
||||
x:Name="AvailableChannelsTreeView"
|
||||
AutoScrollToSelectedItem="False"
|
||||
ItemsSource="{Binding AvailableChannels}"
|
||||
SelectedItems="{Binding SelectedChannels}"
|
||||
SelectionChanged="AvailableChannelsTreeView_OnSelectionChanged"
|
||||
|
||||
@@ -24,6 +24,19 @@
|
||||
BorderThickness="0,1">
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<!-- Theme -->
|
||||
<DockPanel
|
||||
Margin="16,8"
|
||||
LastChildFill="False"
|
||||
ToolTip.Tip="Preferred user interface theme">
|
||||
<TextBlock DockPanel.Dock="Left" Text="Theme" />
|
||||
<ComboBox
|
||||
Width="150"
|
||||
DockPanel.Dock="Right"
|
||||
ItemsSource="{Binding AvailableThemes}"
|
||||
SelectedItem="{Binding Theme}" />
|
||||
</DockPanel>
|
||||
|
||||
<!-- Auto-updates -->
|
||||
<DockPanel
|
||||
Margin="16,8"
|
||||
@@ -35,19 +48,6 @@
|
||||
<ToggleSwitch DockPanel.Dock="Right" IsChecked="{Binding IsAutoUpdateEnabled}" />
|
||||
</DockPanel>
|
||||
|
||||
<!-- Dark mode -->
|
||||
<DockPanel
|
||||
Margin="16,8"
|
||||
LastChildFill="False"
|
||||
ToolTip.Tip="Use darker colors in the UI">
|
||||
<TextBlock DockPanel.Dock="Left" Text="Dark mode" />
|
||||
<ToggleSwitch
|
||||
x:Name="DarkModeToggleSwitch"
|
||||
DockPanel.Dock="Right"
|
||||
IsChecked="{Binding IsDarkModeEnabled}"
|
||||
IsCheckedChanged="DarkModeToggleSwitch_OnIsCheckedChanged" />
|
||||
</DockPanel>
|
||||
|
||||
<!-- Persist token -->
|
||||
<DockPanel
|
||||
Margin="16,8"
|
||||
@@ -66,7 +66,7 @@
|
||||
<ComboBox
|
||||
Width="150"
|
||||
DockPanel.Dock="Right"
|
||||
ItemsSource="{Binding AvailableThreadInclusions}"
|
||||
ItemsSource="{Binding AvailableThreadInclusionModes}"
|
||||
SelectedItem="{Binding ThreadInclusionMode}" />
|
||||
</DockPanel>
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System.Windows;
|
||||
using Avalonia.Interactivity;
|
||||
using DiscordChatExporter.Gui.Framework;
|
||||
using DiscordChatExporter.Gui.Framework;
|
||||
using DiscordChatExporter.Gui.ViewModels.Dialogs;
|
||||
|
||||
namespace DiscordChatExporter.Gui.Views.Dialogs;
|
||||
@@ -8,20 +6,4 @@ namespace DiscordChatExporter.Gui.Views.Dialogs;
|
||||
public partial class SettingsView : UserControl<SettingsViewModel>
|
||||
{
|
||||
public SettingsView() => InitializeComponent();
|
||||
|
||||
private void DarkModeToggleSwitch_OnIsCheckedChanged(object? sender, RoutedEventArgs args)
|
||||
{
|
||||
if (DarkModeToggleSwitch.IsChecked is true)
|
||||
{
|
||||
App.SetDarkTheme();
|
||||
}
|
||||
else if (DarkModeToggleSwitch.IsChecked is false)
|
||||
{
|
||||
App.SetLightTheme();
|
||||
}
|
||||
else
|
||||
{
|
||||
App.SetDefaultTheme();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,7 @@
|
||||
**DiscordChatExporter** is an application that can be used to export message history from any [Discord](https://discord.com) channel to a file.
|
||||
It works with direct messages, group messages, and server channels, and supports Discord's dialect of markdown as well as most other rich media features.
|
||||
|
||||
<!-- Can't use a relative link here due to a bug in markdown parsing -->
|
||||
> ❔ If you have questions or issues, **please refer to the [docs](https://github.com/Tyrrrz/DiscordChatExporter/tree/master/.docs)**.
|
||||
> ❔ If you have questions or issues, **please refer to the [docs](.docs)**.
|
||||
|
||||
> 💬 If you want to chat, **join my [Discord server](https://discord.gg/2SUWKFnHSm)**.
|
||||
|
||||
@@ -51,17 +50,8 @@ To learn more about the war and how you can help, [click here](https://tyrrrz.me
|
||||
- 📦 [AUR](https://aur.archlinux.org/packages/discord-chat-exporter-cli): `discord-chat-exporter-cli`
|
||||
- 📦 [Nix](https://search.nixos.org/packages?query=discordchatexporter-cli): `discordchatexporter-cli`
|
||||
|
||||
> **Important**:
|
||||
> To run **DiscordChatExporter**, you need to make sure that the **.NET 8.0 Runtime** is installed.
|
||||
> You can download it here:
|
||||
>
|
||||
> - [.NET 8.0 Runtime for **macOS x64**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.0-macos-x64-installer)
|
||||
> - [.NET 8.0 Runtime for **macOS arm64**](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.0-macos-arm64-installer)
|
||||
> - [.NET 8.0 Runtime for **Linux**](https://learn.microsoft.com/dotnet/core/install/linux) (find the correct download for your distro)
|
||||
> - On Windows, the runtime should be installed automatically when you run the application for the first time
|
||||
>
|
||||
> This should not be necessary if you install **DiscordChatExporter** using a package manager, as it should take care of the dependencies for you.
|
||||
> This is also not necessary if you are running **DiscordChatExporter** via Docker, because the image already contains the runtime.
|
||||
> **Note**:
|
||||
> If you're unsure which build is right for your system, consult with [this page](https://useragent.cc) to determine your OS and CPU architecture.
|
||||
|
||||
> **Note**:
|
||||
> AUR and Nix packages linked above are maintained by the community.
|
||||
@@ -69,8 +59,7 @@ To learn more about the war and how you can help, [click here](https://tyrrrz.me
|
||||
|
||||
## Features
|
||||
|
||||
- Graphical and command-line interfaces
|
||||
- Fully cross-platform
|
||||
- Cross-platform graphical and command-line interfaces
|
||||
- Authentication via either a user or a bot token
|
||||
- Multiple output formats: HTML (dark/light), TXT, CSV, JSON
|
||||
- Support for markdown, attachments, embeds, emoji, and other rich media features
|
||||
|
||||
Reference in New Issue
Block a user