From 2b97d7c5999360006b7835162d100b07bd3a610b Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 29 Feb 2024 11:29:54 +0800 Subject: [PATCH] feature: do NOT reset scroll offset after recompute diff with same change --- src/ViewModels/DiffContext.cs | 9 ++++++++- src/ViewModels/TwoSideTextDiff.cs | 7 ------- src/ViewModels/WorkingCopy.cs | 8 +++++++- src/Views/TextDiffView.axaml | 7 ++++--- src/Views/TextDiffView.axaml.cs | 19 +++++++++++++++++++ 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/ViewModels/DiffContext.cs b/src/ViewModels/DiffContext.cs index 6e83cc0c..470125aa 100644 --- a/src/ViewModels/DiffContext.cs +++ b/src/ViewModels/DiffContext.cs @@ -1,4 +1,5 @@ -using Avalonia.Threading; +using Avalonia; +using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; using System.IO; using System.Threading.Tasks; @@ -49,6 +50,11 @@ namespace SourceGit.ViewModels { private set => SetProperty(ref _content, value); } + public Vector SyncScrollOffset { + get => _syncScrollOffset; + set => SetProperty(ref _syncScrollOffset, value); + } + public DiffContext(string repo, Models.DiffOption option) { _repo = repo; _option = option; @@ -113,5 +119,6 @@ namespace SourceGit.ViewModels { private bool _isNoChange = false; private bool _isTextDiff = false; private object _content = null; + private Vector _syncScrollOffset = Vector.Zero; } } diff --git a/src/ViewModels/TwoSideTextDiff.cs b/src/ViewModels/TwoSideTextDiff.cs index 07f4cf95..f8bc46d4 100644 --- a/src/ViewModels/TwoSideTextDiff.cs +++ b/src/ViewModels/TwoSideTextDiff.cs @@ -4,11 +4,6 @@ using System.Collections.Generic; namespace SourceGit.ViewModels { public class TwoSideTextDiff : ObservableObject { - public Vector SyncScrollOffset { - get => _syncScrollOffset; - set => SetProperty(ref _syncScrollOffset, value); - } - public string File { get; set; } = string.Empty; public List Old { get; set; } = new List(); public List New { get; set; } = new List(); @@ -46,7 +41,5 @@ namespace SourceGit.ViewModels { for (int i = 0; i < diff; i++) New.Add(new Models.TextDiffLine()); } } - - private Vector _syncScrollOffset; } } diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs index 4a741bbc..01c23125 100644 --- a/src/ViewModels/WorkingCopy.cs +++ b/src/ViewModels/WorkingCopy.cs @@ -1,4 +1,5 @@ -using Avalonia.Controls; +using Avalonia; +using Avalonia.Controls; using Avalonia.Platform.Storage; using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; @@ -194,6 +195,9 @@ namespace SourceGit.ViewModels { // Restore last selection states. if (viewChange != null) { + var scrollOffset = Vector.Zero; + if (_detailContext is DiffContext old) scrollOffset = old.SyncScrollOffset; + if (lastSelectedIsUnstaged) { SelectedUnstagedChange = viewChange; SelectedUnstagedTreeNode = FileTreeNode.SelectByPath(_unstagedTree, viewFile); @@ -201,6 +205,8 @@ namespace SourceGit.ViewModels { SelectedStagedChange = viewChange; SelectedStagedTreeNode = FileTreeNode.SelectByPath(_stagedTree, viewFile); } + + if (_detailContext is DiffContext cur) cur.SyncScrollOffset = scrollOffset; } else { SelectedUnstagedChange = null; SelectedUnstagedTreeNode = null; diff --git a/src/Views/TextDiffView.axaml b/src/Views/TextDiffView.axaml index bba8e3f4..4321137a 100644 --- a/src/Views/TextDiffView.axaml +++ b/src/Views/TextDiffView.axaml @@ -18,13 +18,14 @@ SecondaryFG="{DynamicResource Brush.FG2}" FontFamily="{StaticResource JetBrainsMono}" FontSize="12" - DiffData="{Binding}"/> + DiffData="{Binding}" + SyncScrollOffset="{Binding $parent[v:DiffView].DataContext.(vm:DiffContext).SyncScrollOffset, Mode=TwoWay}"/> SetValue(SecondaryFGProperty, value); } + public static readonly StyledProperty SyncScrollOffsetProperty = + AvaloniaProperty.Register(nameof(SyncScrollOffset)); + + public Vector SyncScrollOffset { + get => GetValue(SyncScrollOffsetProperty); + set => SetValue(SyncScrollOffsetProperty, value); + } + protected override Type StyleKeyOverride => typeof(TextEditor); public CombinedTextDiffPresenter() : base(new TextArea(), new TextDocument()) { @@ -208,6 +216,7 @@ namespace SourceGit.Views { TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this)); TextArea.TextView.LineTransformers.Add(new LineStyleTransformer(this, SecondaryFG)); TextArea.TextView.ContextRequested += OnTextViewContextRequested; + TextArea.TextView.ScrollOffsetChanged += OnTextViewScrollOffsetChanged; if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) { _registryOptions = new RegistryOptions(ThemeName.DarkPlus); @@ -226,6 +235,7 @@ namespace SourceGit.Views { TextArea.TextView.BackgroundRenderers.Clear(); TextArea.TextView.LineTransformers.Clear(); TextArea.TextView.ContextRequested -= OnTextViewContextRequested; + TextArea.TextView.ScrollOffsetChanged -= OnTextViewScrollOffsetChanged; _registryOptions = null; _textMate.Dispose(); _textMate = null; @@ -255,6 +265,10 @@ namespace SourceGit.Views { e.Handled = true; } + private void OnTextViewScrollOffsetChanged(object sender, EventArgs e) { + SyncScrollOffset = TextArea.TextView.ScrollOffset; + } + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); @@ -270,6 +284,11 @@ namespace SourceGit.Views { } else { Text = string.Empty; } + } else if (change.Property == SyncScrollOffsetProperty) { + if (TextArea.TextView.ScrollOffset != SyncScrollOffset) { + IScrollable scrollable = TextArea.TextView; + scrollable.Offset = SyncScrollOffset; + } } else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null && _textMate != null) { if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) { _textMate.SetTheme(_registryOptions.LoadTheme(ThemeName.DarkPlus));