mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-03-31 09:33:03 -06:00
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:
parent
6879fca6fd
commit
c2ee6f047d
|
|
@ -180,7 +180,7 @@ public partial record Message
|
|||
// Currently Discord only supports 1 snapshot per forward
|
||||
var forwardedMessage = json.GetPropertyOrNull("message_snapshots")
|
||||
?.EnumerateArrayOrNull()
|
||||
?.Select(j => j.GetPropertyOrNull("message"))
|
||||
?.Select(j => j.GetPropertyOrNull("message"))
|
||||
.WhereNotNull()
|
||||
.Select(MessageSnapshot.Parse)
|
||||
.FirstOrDefault();
|
||||
|
|
|
|||
|
|
@ -9,14 +9,15 @@ public record MessageReference(
|
|||
MessageReferenceKind Kind,
|
||||
Snowflake? MessageId,
|
||||
Snowflake? ChannelId,
|
||||
Snowflake? GuildId)
|
||||
Snowflake? GuildId
|
||||
)
|
||||
{
|
||||
public static MessageReference Parse(JsonElement json)
|
||||
{
|
||||
var kind =
|
||||
json.GetPropertyOrNull("type")?.GetInt32OrNull()?.Pipe(t => (MessageReferenceKind)t)
|
||||
?? MessageReferenceKind.Default;
|
||||
|
||||
|
||||
var messageId = json.GetPropertyOrNull("message_id")
|
||||
?.GetNonWhiteSpaceStringOrNull()
|
||||
?.Pipe(Snowflake.Parse);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -352,7 +352,7 @@ internal class JsonMessageWriter(Stream stream, ExportContext context)
|
|||
_writer.WriteEndObject();
|
||||
await _writer.FlushAsync(cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
private async ValueTask WriteStickerAsync(
|
||||
Sticker sticker,
|
||||
CancellationToken cancellationToken = default
|
||||
|
|
@ -553,14 +553,14 @@ internal class JsonMessageWriter(Stream stream, ExportContext context)
|
|||
|
||||
_writer.WriteString(
|
||||
"timestamp",
|
||||
Context.NormalizeDate(message.ForwardedMessage.Timestamp)
|
||||
Context.NormalizeDate(message.ForwardedMessage.Timestamp)
|
||||
);
|
||||
|
||||
_writer.WriteString(
|
||||
"timestampEdited",
|
||||
message.ForwardedMessage.EditedTimestamp?.Pipe(Context.NormalizeDate)
|
||||
);
|
||||
|
||||
|
||||
_writer.WriteString(
|
||||
"content",
|
||||
await FormatMarkdownAsync(message.ForwardedMessage.Content, cancellationToken)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public static class CollectionExtensions
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension<T>(IEnumerable<T?> source)
|
||||
where T : struct
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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}"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue