Publish trimmed builds (#1235)

pull/1240/head
Oleksii Holub 1 month ago committed by GitHub
parent b7548756a8
commit 91b7486f45
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -99,7 +99,7 @@ jobs:
# GUI assets aren't suffixed, unlike the CLI assets # GUI assets aren't suffixed, unlike the CLI assets
asset: DiscordChatExporter asset: DiscordChatExporter
runs-on: ubuntu-latest runs-on: ${{ startsWith(matrix.rid, 'win-') && 'windows-latest' || startsWith(matrix.rid, 'osx-') && 'macos-latest' || 'ubuntu-latest' }}
timeout-minutes: 10 timeout-minutes: 10
permissions: permissions:

@ -3,6 +3,8 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<ApplicationIcon>..\favicon.ico</ApplicationIcon> <ApplicationIcon>..\favicon.ico</ApplicationIcon>
<PublishTrimmed>true</PublishTrimmed>
<NoWarn>$(NoWarn);IL2104</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

@ -1,3 +1,37 @@
using CliFx; using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using CliFx;
using DiscordChatExporter.Cli.Commands;
using DiscordChatExporter.Cli.Commands.Converters;
return await new CliApplicationBuilder().AddCommandsFromThisAssembly().Build().RunAsync(args); namespace DiscordChatExporter.Cli;
public static class Program
{
// Explicit references because CliFx relies on reflection and we're publishing with trimming enabled
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(ExportAllCommand))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(ExportChannelsCommand))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(ExportDirectMessagesCommand))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(ExportGuildCommand))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(GetChannelsCommand))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(GetDirectChannelsCommand))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(GetGuildsCommand))]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(GuideCommand))]
[DynamicDependency(
DynamicallyAccessedMemberTypes.All,
typeof(ThreadInclusionModeBindingConverter)
)]
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(TruthyBooleanBindingConverter))]
public static async Task<int> Main(string[] args) =>
await new CliApplicationBuilder()
.AddCommand<ExportAllCommand>()
.AddCommand<ExportChannelsCommand>()
.AddCommand<ExportDirectMessagesCommand>()
.AddCommand<ExportGuildCommand>()
.AddCommand<GetChannelsCommand>()
.AddCommand<GetDirectChannelsCommand>()
.AddCommand<GetGuildsCommand>()
.AddCommand<GuideCommand>()
.Build()
.RunAsync(args);
}

@ -4,6 +4,18 @@
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<AssemblyName>DiscordChatExporter</AssemblyName> <AssemblyName>DiscordChatExporter</AssemblyName>
<ApplicationIcon>..\favicon.ico</ApplicationIcon> <ApplicationIcon>..\favicon.ico</ApplicationIcon>
<PublishTrimmed>true</PublishTrimmed>
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
<NoWarn>$(NoWarn);IL2104</NoWarn>
</PropertyGroup>
<!-- Avalonia-related settings -->
<PropertyGroup>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<!-- Warnings not valid when using compiled bindings -->
<NoWarn>$(NoWarn);IL2026</NoWarn>
<!-- Warnings about Material.Avalonia having peer dependencies that we don't use -->
<NoWarn>$(NoWarn);IL2035</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

@ -1,25 +1,31 @@
using System; using Avalonia.Controls;
using Avalonia.Controls;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using DiscordChatExporter.Gui.ViewModels;
using DiscordChatExporter.Gui.ViewModels.Components;
using DiscordChatExporter.Gui.ViewModels.Dialogs;
using DiscordChatExporter.Gui.Views;
using DiscordChatExporter.Gui.Views.Components;
using DiscordChatExporter.Gui.Views.Dialogs;
namespace DiscordChatExporter.Gui.Framework; namespace DiscordChatExporter.Gui.Framework;
public partial class ViewManager public partial class ViewManager
{ {
public Control? TryBindView(ViewModelBase viewModel) private Control? TryCreateView(ViewModelBase viewModel) =>
viewModel switch
{ {
var name = viewModel MainViewModel => new MainView(),
.GetType() DashboardViewModel => new DashboardView(),
.FullName?.Replace("ViewModel", "View", StringComparison.Ordinal); ExportSetupViewModel => new ExportSetupView(),
MessageBoxViewModel => new MessageBoxView(),
if (string.IsNullOrWhiteSpace(name)) SettingsViewModel => new SettingsView(),
return null; _ => null
};
var type = Type.GetType(name); public Control? TryBindView(ViewModelBase viewModel)
if (type is null) {
return null; var view = TryCreateView(viewModel);
if (view is null)
if (Activator.CreateInstance(type) is not Control view)
return null; return null;
view.DataContext ??= viewModel; view.DataContext ??= viewModel;

@ -9,11 +9,8 @@
xmlns:materialIcons="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia" xmlns:materialIcons="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:materialStyles="clr-namespace:Material.Styles.Controls;assembly=Material.Styles" xmlns:materialStyles="clr-namespace:Material.Styles.Controls;assembly=Material.Styles"
x:Name="UserControl" x:Name="UserControl"
x:DataType="components:DashboardViewModel"
Loaded="UserControl_OnLoaded"> Loaded="UserControl_OnLoaded">
<Design.DataContext>
<components:DashboardViewModel />
</Design.DataContext>
<DockPanel> <DockPanel>
<!-- Header --> <!-- Header -->
<StackPanel <StackPanel
@ -95,126 +92,6 @@
</Style> </Style>
</Style> </Style>
</Panel.Styles> </Panel.Styles>
<!-- Placeholder / usage instructions -->
<Panel IsVisible="{Binding !AvailableGuilds.Count}">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<TextBlock
Margin="32,16"
FontSize="14"
FontWeight="Light"
LineHeight="23">
<!-- User token -->
<InlineUIContainer>
<materialIcons:MaterialIcon
Width="18"
Height="18"
Margin="0,-2,0,0"
Foreground="{DynamicResource PrimaryHueMidBrush}"
Kind="Account" />
</InlineUIContainer>
<Run Text="" />
<Run
FontSize="16"
FontWeight="SemiBold"
Text="To get the token for your personal account:" />
<LineBreak />
<Run Text="* Automating user accounts is technically against TOS —" />
<Run FontWeight="SemiBold" Text="use at your own risk" /><Run Text="!" />
<LineBreak />
<Run Text="1. Open Discord in your" />
<controls:HyperLink Command="{Binding OpenDiscordCommand}" Text="web browser" />
<Run Text="and login" />
<LineBreak />
<Run Text="2. Open any server or direct message channel" />
<LineBreak />
<Run Text="3. Press" />
<Run FontWeight="SemiBold" Text="Ctrl+Shift+I" />
<Run Text="to show developer tools" />
<LineBreak />
<Run Text="4. Navigate to the" />
<Run FontWeight="SemiBold" Text="Network" />
<Run Text="tab" />
<LineBreak />
<Run Text="5. Press" />
<Run FontWeight="SemiBold" Text="Ctrl+R" />
<Run Text="to reload" />
<LineBreak />
<Run Text="6. Switch between random channels to trigger network requests" />
<LineBreak />
<Run Text="7. Search for a request that starts with" />
<Run FontWeight="SemiBold" Text="messages" />
<LineBreak />
<Run Text="8. Select the" />
<Run FontWeight="SemiBold" Text="Headers" />
<Run Text="tab on the right" />
<LineBreak />
<Run Text="9. Scroll down to the" />
<Run FontWeight="SemiBold" Text="Request Headers" />
<Run Text="section" />
<LineBreak />
<Run Text="10. Copy the value of the" />
<Run FontWeight="SemiBold" Text="authorization" />
<Run Text="header" />
<LineBreak />
<LineBreak />
<!-- Bot token -->
<InlineUIContainer>
<materialIcons:MaterialIcon
Width="18"
Height="18"
Margin="0,-2,0,0"
Foreground="{DynamicResource PrimaryHueMidBrush}"
Kind="Robot" />
</InlineUIContainer>
<Run Text="" />
<Run
FontSize="16"
FontWeight="SemiBold"
Text="To get the token for your bot:" />
<LineBreak />
<Run Text="1. Open Discord" />
<controls:HyperLink Command="{Binding OpenDiscordDeveloperPortalCommand}" Text="developer portal" />
<LineBreak />
<Run Text="2. Open your application's settings" />
<LineBreak />
<Run Text="3. Navigate to the" />
<Run FontWeight="SemiBold" Text="Bot" />
<Run Text="section on the left" />
<LineBreak />
<Run Text="4. Under" />
<Run FontWeight="SemiBold" Text="Token" />
<Run Text="click" />
<Run FontWeight="SemiBold" Text="Copy" />
<LineBreak />
<Run Text="* Your bot needs to have the" />
<Run FontWeight="SemiBold" Text="Message Content Intent" />
<Run Text="enabled to read messages" />
<LineBreak />
<LineBreak />
<Run Text="If you have questions or issues, please refer to the" />
<controls:HyperLink Command="{Binding ShowHelpCommand}" Text="documentation" />
</TextBlock>
</ScrollViewer>
</Panel>
<!-- Guilds and channels --> <!-- Guilds and channels -->
<Grid ColumnDefinitions="Auto,*" IsVisible="{Binding !!AvailableGuilds.Count}"> <Grid ColumnDefinitions="Auto,*" IsVisible="{Binding !!AvailableGuilds.Count}">
<!-- Guilds --> <!-- Guilds -->
@ -339,6 +216,126 @@
</Border> </Border>
</Grid> </Grid>
<!-- Placeholder / usage instructions -->
<Panel IsVisible="{Binding !AvailableGuilds.Count}">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<TextBlock
Margin="32,16"
FontSize="14"
FontWeight="Light"
LineHeight="23">
<!-- User token -->
<InlineUIContainer>
<materialIcons:MaterialIcon
Width="18"
Height="18"
Margin="0,-2,0,0"
Foreground="{DynamicResource PrimaryHueMidBrush}"
Kind="Account" />
</InlineUIContainer>
<Run Text="" />
<Run
FontSize="16"
FontWeight="SemiBold"
Text="To get the token for your personal account:" />
<LineBreak />
<Run Text="* Automating user accounts is technically against TOS —" />
<Run FontWeight="SemiBold" Text="use at your own risk" /><Run Text="!" />
<LineBreak />
<Run Text="1. Open Discord in your" />
<controls:HyperLink Command="{Binding OpenDiscordCommand}" Text="web browser" />
<Run Text="and login" />
<LineBreak />
<Run Text="2. Open any server or direct message channel" />
<LineBreak />
<Run Text="3. Press" />
<Run FontWeight="SemiBold" Text="Ctrl+Shift+I" />
<Run Text="to show developer tools" />
<LineBreak />
<Run Text="4. Navigate to the" />
<Run FontWeight="SemiBold" Text="Network" />
<Run Text="tab" />
<LineBreak />
<Run Text="5. Press" />
<Run FontWeight="SemiBold" Text="Ctrl+R" />
<Run Text="to reload" />
<LineBreak />
<Run Text="6. Switch between random channels to trigger network requests" />
<LineBreak />
<Run Text="7. Search for a request that starts with" />
<Run FontWeight="SemiBold" Text="messages" />
<LineBreak />
<Run Text="8. Select the" />
<Run FontWeight="SemiBold" Text="Headers" />
<Run Text="tab on the right" />
<LineBreak />
<Run Text="9. Scroll down to the" />
<Run FontWeight="SemiBold" Text="Request Headers" />
<Run Text="section" />
<LineBreak />
<Run Text="10. Copy the value of the" />
<Run FontWeight="SemiBold" Text="authorization" />
<Run Text="header" />
<LineBreak />
<LineBreak />
<!-- Bot token -->
<InlineUIContainer>
<materialIcons:MaterialIcon
Width="18"
Height="18"
Margin="0,-2,0,0"
Foreground="{DynamicResource PrimaryHueMidBrush}"
Kind="Robot" />
</InlineUIContainer>
<Run Text="" />
<Run
FontSize="16"
FontWeight="SemiBold"
Text="To get the token for your bot:" />
<LineBreak />
<Run Text="1. Open Discord" />
<controls:HyperLink Command="{Binding OpenDiscordDeveloperPortalCommand}" Text="developer portal" />
<LineBreak />
<Run Text="2. Open your application's settings" />
<LineBreak />
<Run Text="3. Navigate to the" />
<Run FontWeight="SemiBold" Text="Bot" />
<Run Text="section on the left" />
<LineBreak />
<Run Text="4. Under" />
<Run FontWeight="SemiBold" Text="Token" />
<Run Text="click" />
<Run FontWeight="SemiBold" Text="Copy" />
<LineBreak />
<Run Text="* Your bot needs to have the" />
<Run FontWeight="SemiBold" Text="Message Content Intent" />
<Run Text="enabled to read messages" />
<LineBreak />
<LineBreak />
<Run Text="If you have questions or issues, please refer to the" />
<controls:HyperLink Command="{Binding ShowHelpCommand}" Text="documentation" />
</TextBlock>
</ScrollViewer>
</Panel>
<!-- Export button --> <!-- Export button -->
<Button <Button
Width="56" Width="56"

@ -1,13 +1,14 @@
<UserControl <UserControl
x:Class="DiscordChatExporter.Gui.Views.Controls.HyperLink" x:Class="DiscordChatExporter.Gui.Views.Controls.HyperLink"
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"
xmlns:controls="clr-namespace:DiscordChatExporter.Gui.Views.Controls">
<TextBlock <TextBlock
x:Name="TextBlock" x:Name="TextBlock"
Cursor="Hand" Cursor="Hand"
Foreground="{DynamicResource MaterialSecondaryDarkBrush}" Foreground="{DynamicResource MaterialSecondaryDarkBrush}"
PointerReleased="TextBlock_OnPointerReleased" PointerReleased="TextBlock_OnPointerReleased"
Text="{Binding $parent[UserControl].Text, Mode=OneWay}"> Text="{Binding $parent[controls:HyperLink].Text, Mode=OneWay}">
<TextBlock.Styles> <TextBlock.Styles>
<Style Selector="TextBlock"> <Style Selector="TextBlock">
<Style Selector="^:pointerover"> <Style Selector="^:pointerover">

@ -10,11 +10,8 @@
xmlns:utils="clr-namespace:DiscordChatExporter.Gui.Utils" xmlns:utils="clr-namespace:DiscordChatExporter.Gui.Utils"
x:Name="UserControl" x:Name="UserControl"
Width="380" Width="380"
x:DataType="dialogs:ExportSetupViewModel"
Loaded="UserControl_OnLoaded"> Loaded="UserControl_OnLoaded">
<Design.DataContext>
<dialogs:ExportSetupViewModel />
</Design.DataContext>
<Grid RowDefinitions="Auto,*,Auto"> <Grid RowDefinitions="Auto,*,Auto">
<!-- Guild/channel info --> <!-- Guild/channel info -->
<Grid <Grid
@ -40,7 +37,7 @@
FontWeight="Light" FontWeight="Light"
IsVisible="{Binding !IsSingleChannel}" IsVisible="{Binding !IsSingleChannel}"
TextTrimming="CharacterEllipsis"> TextTrimming="CharacterEllipsis">
<Run Text="{Binding Channels.Count, Mode=OneWay}" /> <Run Text="{Binding Channels.Count, FallbackValue=0, Mode=OneWay}" />
<Run Text="channels selected" /> <Run Text="channels selected" />
</TextBlock> </TextBlock>

@ -4,11 +4,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dialogs="clr-namespace:DiscordChatExporter.Gui.ViewModels.Dialogs" xmlns:dialogs="clr-namespace:DiscordChatExporter.Gui.ViewModels.Dialogs"
xmlns:system="clr-namespace:System;assembly=System.Runtime" xmlns:system="clr-namespace:System;assembly=System.Runtime"
Width="500"> Width="500"
<Design.DataContext> x:DataType="dialogs:MessageBoxViewModel">
<dialogs:MessageBoxViewModel />
</Design.DataContext>
<Grid RowDefinitions="Auto,*,Auto"> <Grid RowDefinitions="Auto,*,Auto">
<!-- Title --> <!-- Title -->
<TextBlock <TextBlock

@ -4,11 +4,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:DiscordChatExporter.Gui.Converters" xmlns:converters="clr-namespace:DiscordChatExporter.Gui.Converters"
xmlns:dialogs="clr-namespace:DiscordChatExporter.Gui.ViewModels.Dialogs" xmlns:dialogs="clr-namespace:DiscordChatExporter.Gui.ViewModels.Dialogs"
Width="380"> Width="380"
<Design.DataContext> x:DataType="dialogs:SettingsViewModel">
<dialogs:SettingsViewModel />
</Design.DataContext>
<Grid RowDefinitions="Auto,*,Auto"> <Grid RowDefinitions="Auto,*,Auto">
<TextBlock <TextBlock
Grid.Row="0" Grid.Row="0"

@ -10,13 +10,10 @@
Height="625" Height="625"
MinWidth="600" MinWidth="600"
MinHeight="400" MinHeight="400"
x:DataType="viewModels:MainViewModel"
Icon="/favicon.ico" Icon="/favicon.ico"
RenderOptions.BitmapInterpolationMode="HighQuality" RenderOptions.BitmapInterpolationMode="HighQuality"
WindowStartupLocation="CenterScreen"> WindowStartupLocation="CenterScreen">
<Design.DataContext>
<viewModels:MainViewModel />
</Design.DataContext>
<dialogHostAvalonia:DialogHost <dialogHostAvalonia:DialogHost
x:Name="DialogHost" x:Name="DialogHost"
CloseOnClickAway="False" CloseOnClickAway="False"

Loading…
Cancel
Save