forked from sim0n00ps/OF-DL
196 lines
5.5 KiB
C#
196 lines
5.5 KiB
C#
using System.Diagnostics;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Input;
|
|
using Avalonia.Interactivity;
|
|
using Avalonia.Platform;
|
|
using Avalonia.Platform.Storage;
|
|
using OF_DL.Gui.ViewModels;
|
|
|
|
namespace OF_DL.Gui.Views;
|
|
|
|
public partial class MainWindow : Window
|
|
{
|
|
private const string DiscordInviteUrl = "https://discord.com/invite/6bUW8EJ53j";
|
|
private const string DocumentationUrl = "https://docs.ofdl.tools/";
|
|
private bool _hasInitialized;
|
|
public MainWindowViewModel? ViewModel => DataContext as MainWindowViewModel;
|
|
|
|
public MainWindow()
|
|
{
|
|
InitializeComponent();
|
|
Icon = new WindowIcon(AssetLoader.Open(new Uri("avares://OF DL.Gui/Assets/icon.ico")));
|
|
Opened += OnOpened;
|
|
}
|
|
|
|
private async void OnOpened(object? sender, EventArgs e)
|
|
{
|
|
if (_hasInitialized)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_hasInitialized = true;
|
|
if (DataContext is MainWindowViewModel vm)
|
|
{
|
|
await vm.InitializeAsync();
|
|
}
|
|
}
|
|
|
|
private async void OnBrowseFfmpegPathClick(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (DataContext is not MainWindowViewModel vm)
|
|
{
|
|
return;
|
|
}
|
|
|
|
TopLevel? topLevel = GetTopLevel(this);
|
|
if (topLevel?.StorageProvider == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
IReadOnlyList<IStorageFile> selectedFiles = await topLevel.StorageProvider.OpenFilePickerAsync(
|
|
new FilePickerOpenOptions { Title = "Select FFmpeg executable", AllowMultiple = false });
|
|
|
|
IStorageFile? selectedFile = selectedFiles.FirstOrDefault();
|
|
if (selectedFile == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
string? localPath = selectedFile.TryGetLocalPath();
|
|
if (!string.IsNullOrWhiteSpace(localPath))
|
|
{
|
|
vm.SetFfmpegPath(localPath);
|
|
return;
|
|
}
|
|
|
|
vm.SetFfmpegPath(selectedFile.Name);
|
|
}
|
|
|
|
private async void OnBrowseFfprobePathClick(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (DataContext is not MainWindowViewModel vm)
|
|
{
|
|
return;
|
|
}
|
|
|
|
TopLevel? topLevel = GetTopLevel(this);
|
|
if (topLevel?.StorageProvider == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
IReadOnlyList<IStorageFile> selectedFiles = await topLevel.StorageProvider.OpenFilePickerAsync(
|
|
new FilePickerOpenOptions { Title = "Select FFprobe executable", AllowMultiple = false });
|
|
|
|
IStorageFile? selectedFile = selectedFiles.FirstOrDefault();
|
|
if (selectedFile == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
string? localPath = selectedFile.TryGetLocalPath();
|
|
if (!string.IsNullOrWhiteSpace(localPath))
|
|
{
|
|
vm.SetFfprobePath(localPath);
|
|
return;
|
|
}
|
|
|
|
vm.SetFfprobePath(selectedFile.Name);
|
|
}
|
|
|
|
private async void OnBrowseDownloadPathClick(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (DataContext is not MainWindowViewModel vm)
|
|
{
|
|
return;
|
|
}
|
|
|
|
TopLevel? topLevel = GetTopLevel(this);
|
|
if (topLevel?.StorageProvider == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
IReadOnlyList<IStorageFolder> selectedFolders = await topLevel.StorageProvider.OpenFolderPickerAsync(
|
|
new FolderPickerOpenOptions { Title = "Select download folder", AllowMultiple = false });
|
|
|
|
IStorageFolder? selectedFolder = selectedFolders.FirstOrDefault();
|
|
if (selectedFolder == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
string? localPath = selectedFolder.TryGetLocalPath();
|
|
if (!string.IsNullOrWhiteSpace(localPath))
|
|
{
|
|
vm.SetDownloadPath(localPath);
|
|
return;
|
|
}
|
|
|
|
vm.SetDownloadPath(selectedFolder.Name);
|
|
}
|
|
|
|
private async void OnJoinDiscordClick(object? sender, RoutedEventArgs e) =>
|
|
await OpenExternalUrlAsync(DiscordInviteUrl);
|
|
|
|
private async void OnDocumentationClick(object? sender, RoutedEventArgs e) =>
|
|
await OpenExternalUrlAsync(DocumentationUrl);
|
|
|
|
private void OnFaqClick(object? sender, RoutedEventArgs e)
|
|
{
|
|
FaqWindow faqWindow = new()
|
|
{
|
|
WindowStartupLocation = WindowStartupLocation.CenterOwner
|
|
};
|
|
faqWindow.Show(this);
|
|
}
|
|
|
|
private void OnAboutClick(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (DataContext is not MainWindowViewModel vm)
|
|
{
|
|
return;
|
|
}
|
|
|
|
AboutWindow aboutWindow = new(vm.ProgramVersion, vm.FfmpegVersion, vm.FfprobeVersion)
|
|
{
|
|
WindowStartupLocation = WindowStartupLocation.CenterOwner
|
|
};
|
|
aboutWindow.Show(this);
|
|
}
|
|
|
|
private async Task OpenExternalUrlAsync(string url)
|
|
{
|
|
try
|
|
{
|
|
ProcessStartInfo processStartInfo = new(url) { UseShellExecute = true };
|
|
|
|
Process.Start(processStartInfo);
|
|
}
|
|
catch
|
|
{
|
|
await Task.CompletedTask;
|
|
}
|
|
}
|
|
|
|
private void OnModalOverlayClicked(object? sender, PointerPressedEventArgs e)
|
|
{
|
|
// Only handle clicks on the overlay itself (the Grid background)
|
|
if (DataContext is not MainWindowViewModel vm)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Execute cancel command on any open modal
|
|
vm.CreatorConfigEditor.ModalViewModel?.CancelCommand?.Execute(null);
|
|
vm.CancelSinglePostOrMessageCommand.Execute(null);
|
|
vm.CancelMissingCdmWarningCommand.Execute(null);
|
|
}
|
|
|
|
private void OnModalContentClicked(object? sender, PointerPressedEventArgs e) =>
|
|
// Stop the event from bubbling up to the overlay
|
|
e.Handled = true;
|
|
}
|