adams-toolkit

codigo-fonte GPL-3.0 · espelho oficial · commit b208bae5
EditorWindow.xaml.cs · 105 linhas · raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
using System.Windows;
using System.Windows.Input;
using AdamsToolkit.Core;
using AdamsToolkit.Views;

namespace AdamsToolkit;

/// <summary>
/// Janela do Editor de Clips (v1.71, ex-Adams Clips). Vive à parte da janela principal:
/// abre sozinha (ecrã de escolha / ficheiro de vídeo por argumento) ou a partir da sidebar.
/// FFmpeg é descarregado na 1ª abertura; até lá o editor não é sequer construído.
/// </summary>
public partial class EditorWindow : Window
{
    private static EditorWindow? _instance;
    private EditorView? _editor;
    private string? _pendingFile;
    private CancellationTokenSource? _setupCts;

    /// <summary>Uma janela só: abre (ou traz para a frente) e opcionalmente carrega um ficheiro.</summary>
    public static EditorWindow Open(string? file = null)
    {
        if (_instance == null)
        {
            _instance = new EditorWindow();
            _instance.Closed += (_, _) => _instance = null;
            _instance._pendingFile = file;
            _instance.Show();
        }
        else
        {
            if (_instance.WindowState == WindowState.Minimized) _instance.WindowState = WindowState.Normal;
            _instance.Activate();
            if (file != null) _ = _instance.LoadAsync(file);
        }
        return _instance;
    }

    public static bool IsOpen => _instance != null;

    private EditorWindow()
    {
        InitializeComponent();
        VersionText.Text = $"v{SelfUpdater.CurrentVersion}";
        Loaded += async (_, _) => await EnsureReadyAsync();
        Closing += (_, _) => { _setupCts?.Cancel(); _editor?.Shutdown(); };
        // cantos: clip geométrico na raiz (Border.CornerRadius não corta os filhos)
        void Clip() { var r = WindowState == WindowState.Maximized ? 0 : 14; RootBorder.Clip = new System.Windows.Media.RectangleGeometry(new Rect(0, 0, RootBorder.ActualWidth, RootBorder.ActualHeight), r, r); }
        RootBorder.SizeChanged += (_, _) => Clip();
        StateChanged += (_, _) => Clip();
        StateChanged += (_, _) => { var max = WindowState == WindowState.Maximized; RootBorder.CornerRadius = new CornerRadius(max ? 0 : 14); TitleBar.CornerRadius = new CornerRadius(max ? 0 : 13, max ? 0 : 13, 0, 0); };
    }

    private async Task EnsureReadyAsync()
    {
        if (FfmpegManager.IsReady) { Mount(); return; }
        SetupPanel.Visibility = Visibility.Visible;
        RetryBtn.Visibility = Visibility.Collapsed;
        _setupCts = new CancellationTokenSource();
        try
        {
            var prog = new Progress<(double pct, string msg)>(p => { SetupBar.Value = p.pct; SetupText.Text = p.msg; });
            await FfmpegManager.EnsureAsync(prog, _setupCts.Token);
            SetupPanel.Visibility = Visibility.Collapsed;
            Mount();
        }
        catch (OperationCanceledException) { }
        catch (Exception ex)
        {
            SetupText.Text = "Não deu: " + ex.Message;
            RetryBtn.Visibility = Visibility.Visible;
        }
    }

    private void Mount()
    {
        if (_editor != null) return;
        Task.Run(VideoEditor.CleanupProxies);
        _editor = new EditorView();
        Host.Content = _editor;
        _editor.Focus();
        if (_pendingFile != null) { var f = _pendingFile; _pendingFile = null; _ = LoadAsync(f); }
    }

    private async Task LoadAsync(string file)
    {
        if (_editor == null) { _pendingFile = file; return; }
        try { await _editor.OpenAsync(file); } catch (Exception ex) { EditorPaths.LogCrash(ex); }
    }

    private async void Retry_Click(object s, RoutedEventArgs e) => await EnsureReadyAsync();

    // Do editor para o Toolkit: se a janela principal existir, mostra-a; senão cria-a (passa pelo login normal).
    private void Toolkit_Click(object s, RoutedEventArgs e) => App.ShowToolkit();

    // ---- chrome ----
    private void TitleBar_Drag(object s, MouseButtonEventArgs e)
    {
        if (e.ClickCount == 2) { Maximize_Click(s, e); return; }
        if (e.ButtonState == MouseButtonState.Pressed && WindowState == WindowState.Normal) DragMove();
    }
    private void Minimize_Click(object s, RoutedEventArgs e) => WindowState = WindowState.Minimized;
    private void Maximize_Click(object s, RoutedEventArgs e) => WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
    private void Close_Click(object s, RoutedEventArgs e) => Close();
}