GUI: double-clicking a child-less server auto-opens export setup

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-02-27 16:15:04 +00:00
parent 6879fca6fd
commit c2ee6f047d
9 changed files with 78 additions and 25 deletions

View file

@ -9,7 +9,8 @@ public record MessageReference(
MessageReferenceKind Kind,
Snowflake? MessageId,
Snowflake? ChannelId,
Snowflake? GuildId)
Snowflake? GuildId
)
{
public static MessageReference Parse(JsonElement json)
{

View file

@ -15,7 +15,8 @@ public record MessageSnapshot(
string Content,
IReadOnlyList<Attachment> Attachments,
IReadOnlyList<Embed> Embeds,
IReadOnlyList<Sticker> Stickers)
IReadOnlyList<Sticker> Stickers
)
{
public static MessageSnapshot Parse(JsonElement json)
{
@ -23,37 +24,35 @@ public record MessageSnapshot(
json.GetPropertyOrNull("timestamp")?.GetDateTimeOffsetOrNull()
?? DateTimeOffset.MinValue;
var editedTimestamp = json
.GetPropertyOrNull("edited_timestamp")
?.GetDateTimeOffsetOrNull();
var editedTimestamp = json.GetPropertyOrNull("edited_timestamp")?.GetDateTimeOffsetOrNull();
var content = json.GetPropertyOrNull("content")?.GetStringOrNull() ?? "";
var attachments =
json
.GetPropertyOrNull("attachments")
json.GetPropertyOrNull("attachments")
?.EnumerateArrayOrNull()
?.Select(Attachment.Parse)
.ToArray()
?? [];
var embeds =
json
.GetPropertyOrNull("embeds")
?.EnumerateArrayOrNull()
?.Select(Embed.Parse)
.ToArray()
json.GetPropertyOrNull("embeds")?.EnumerateArrayOrNull()?.Select(Embed.Parse).ToArray()
?? [];
var stickers =
json
.GetPropertyOrNull("sticker_items")
json.GetPropertyOrNull("sticker_items")
?.EnumerateArrayOrNull()
?.Select(Sticker.Parse)
.ToArray()
?? [];
return new MessageSnapshot(timestamp,
editedTimestamp, content, attachments, embeds, stickers);
return new MessageSnapshot(
timestamp,
editedTimestamp,
content,
attachments,
embeds,
stickers
);
}
}

View file

@ -553,7 +553,7 @@ internal class JsonMessageWriter(Stream stream, ExportContext context)
_writer.WriteString(
"timestamp",
Context.NormalizeDate(message.ForwardedMessage.Timestamp)
Context.NormalizeDate(message.ForwardedMessage.Timestamp)
);
_writer.WriteString(

View file

@ -239,9 +239,9 @@ internal class PlainTextMessageWriter(Stream stream, ExportContext context)
);
}
await _writer.WriteLineAsync(
$"Originally sent: {Context.FormatDate(forwardedMessage.Timestamp)}"
);
await _writer.WriteLineAsync(
$"Originally sent: {Context.FormatDate(forwardedMessage.Timestamp)}"
);
await WriteAttachmentsAsync(forwardedMessage.Attachments, cancellationToken);
await WriteEmbedsAsync(forwardedMessage.Embeds, cancellationToken);

View file

@ -223,6 +223,54 @@ public partial class DashboardViewModel : ViewModelBase
}
}
[RelayCommand]
private async Task ShowSetupIfSingleChannelAsync()
{
// Wait for any in-progress channel loading to complete
if (IsBusy)
{
var tcs = new TaskCompletionSource();
void Handler(object? _, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(IsBusy) && !IsBusy)
tcs.TrySetResult();
}
PropertyChanged += Handler;
// Re-check after subscribing to avoid missing the transition
if (!IsBusy)
{
PropertyChanged -= Handler;
}
else
{
try
{
await tcs.Task;
}
finally
{
PropertyChanged -= Handler;
}
}
}
// Only auto-export when there is exactly one child-less (non-category) channel
if (
AvailableChannels is not { Count: 1 }
|| AvailableChannels[0].Children.Count != 0
|| AvailableChannels[0].Channel.IsCategory
)
return;
SelectedChannels.Clear();
SelectedChannels.Add(AvailableChannels[0]);
await ExportAsync();
}
private bool CanExport() =>
!IsBusy && _discord is not null && SelectedGuild is not null && SelectedChannels.Any();

View file

@ -99,6 +99,7 @@
BorderThickness="0,0,1,0"
Grid.Column="0">
<ListBox
DoubleTapped="AvailableGuildsListBox_OnDoubleTapped"
ItemsSource="{Binding AvailableGuilds}"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
SelectedItem="{Binding SelectedGuild}"

View file

@ -1,5 +1,6 @@
using System.Linq;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using DiscordChatExporter.Core.Discord.Data;
using DiscordChatExporter.Gui.Framework;
@ -22,6 +23,9 @@ public partial class DashboardView : UserControl<DashboardViewModel>
SelectionChangedEventArgs args
) => DataContext.PullChannelsCommand.Execute(null);
private void AvailableGuildsListBox_OnDoubleTapped(object? sender, TappedEventArgs args) =>
DataContext.ShowSetupIfSingleChannelCommand.Execute(null);
private void AvailableChannelsTreeView_OnSelectionChanged(
object? sender,
SelectionChangedEventArgs args