diff --git a/src/ViewModels/CheckoutCommandPalette.cs b/src/ViewModels/CheckoutCommandPalette.cs new file mode 100644 index 00000000..5caf0989 --- /dev/null +++ b/src/ViewModels/CheckoutCommandPalette.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace SourceGit.ViewModels +{ + public class CheckoutCommandPalette : ICommandPalette + { + public List Branches + { + get => _branches; + private set => SetProperty(ref _branches, value); + } + + public Models.Branch SelectedBranch + { + get => _selectedBranch; + set => SetProperty(ref _selectedBranch, value); + } + + public string Filter + { + get => _filter; + set + { + if (SetProperty(ref _filter, value)) + UpdateBranches(); + } + } + + public CheckoutCommandPalette(Launcher launcher, Repository repo) + { + _launcher = launcher; + _repo = repo; + UpdateBranches(); + } + + public override void Cleanup() + { + _launcher = null; + _repo = null; + _branches.Clear(); + _selectedBranch = null; + _filter = null; + } + + public void ClearFilter() + { + Filter = string.Empty; + } + + public async Task ExecAsync() + { + _launcher.CommandPalette = null; + + if (_selectedBranch != null) + await _repo.CheckoutBranchAsync(_selectedBranch); + + Dispose(); + GC.Collect(); + } + + private void UpdateBranches() + { + var current = _repo.CurrentBranch; + if (current == null) + return; + + var branches = new List(); + foreach (var b in _repo.Branches) + { + if (b == current) + continue; + + if (string.IsNullOrEmpty(_filter) || b.FriendlyName.Contains(_filter, StringComparison.OrdinalIgnoreCase)) + branches.Add(b); + } + + branches.Sort((l, r) => + { + if (l.IsLocal == r.IsLocal) + return l.Name.CompareTo(r.Name); + + return l.IsLocal ? -1 : 1; + }); + + Branches = branches; + } + + private Launcher _launcher; + private Repository _repo; + private List _branches = []; + private Models.Branch _selectedBranch = null; + private string _filter; + } +} diff --git a/src/ViewModels/RepositoryCommandPalette.cs b/src/ViewModels/RepositoryCommandPalette.cs index 6dfed4bc..dee676dc 100644 --- a/src/ViewModels/RepositoryCommandPalette.cs +++ b/src/ViewModels/RepositoryCommandPalette.cs @@ -45,9 +45,21 @@ namespace SourceGit.ViewModels _launcher = launcher; _repo = repo; - _cmds.Add(new("OpenFile", () => + _cmds.Add(new("Blame", () => { - var sub = new OpenFileCommandPalette(_launcher, _repo.FullPath); + var sub = new BlameCommandPalette(_launcher, _repo.FullPath); + _launcher.OpenCommandPalette(sub); + })); + + _cmds.Add(new("BranchCompare", () => + { + var sub = new BranchCompareCommandPalette(_launcher, _repo); + _launcher.OpenCommandPalette(sub); + })); + + _cmds.Add(new("Checkout", () => + { + var sub = new CheckoutCommandPalette(_launcher, _repo); _launcher.OpenCommandPalette(sub); })); @@ -57,21 +69,15 @@ namespace SourceGit.ViewModels _launcher.OpenCommandPalette(sub); })); - _cmds.Add(new("Blame", () => - { - var sub = new BlameCommandPalette(_launcher, _repo.FullPath); - _launcher.OpenCommandPalette(sub); - })); - _cmds.Add(new("Merge", () => { var sub = new MergeCommandPalette(_launcher, _repo); _launcher.OpenCommandPalette(sub); })); - _cmds.Add(new("BranchCompare", () => + _cmds.Add(new("OpenFile", () => { - var sub = new BranchCompareCommandPalette(_launcher, _repo); + var sub = new OpenFileCommandPalette(_launcher, _repo.FullPath); _launcher.OpenCommandPalette(sub); })); diff --git a/src/Views/CheckoutCommandPalette.axaml b/src/Views/CheckoutCommandPalette.axaml new file mode 100644 index 00000000..17897a26 --- /dev/null +++ b/src/Views/CheckoutCommandPalette.axaml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Views/CheckoutCommandPalette.axaml.cs b/src/Views/CheckoutCommandPalette.axaml.cs new file mode 100644 index 00000000..2528aff4 --- /dev/null +++ b/src/Views/CheckoutCommandPalette.axaml.cs @@ -0,0 +1,66 @@ +using Avalonia.Controls; +using Avalonia.Input; + +namespace SourceGit.Views +{ + public partial class CheckoutCommandPalette : UserControl + { + public CheckoutCommandPalette() + { + InitializeComponent(); + } + + protected override async void OnKeyDown(KeyEventArgs e) + { + base.OnKeyDown(e); + + if (DataContext is not ViewModels.CheckoutCommandPalette vm) + return; + + if (e.Key == Key.Enter) + { + await vm.ExecAsync(); + e.Handled = true; + } + else if (e.Key == Key.Up) + { + if (BranchListBox.IsKeyboardFocusWithin) + { + FilterTextBox.Focus(NavigationMethod.Directional); + e.Handled = true; + return; + } + } + else if (e.Key == Key.Down || e.Key == Key.Tab) + { + if (FilterTextBox.IsKeyboardFocusWithin) + { + if (vm.Branches.Count > 0) + { + BranchListBox.Focus(NavigationMethod.Directional); + vm.SelectedBranch = vm.Branches[0]; + } + + e.Handled = true; + return; + } + + if (BranchListBox.IsKeyboardFocusWithin && e.Key == Key.Tab) + { + FilterTextBox.Focus(NavigationMethod.Directional); + e.Handled = true; + return; + } + } + } + + private async void OnItemTapped(object sender, TappedEventArgs e) + { + if (DataContext is ViewModels.CheckoutCommandPalette vm) + { + await vm.ExecAsync(); + e.Handled = true; + } + } + } +}