11using System ;
22using System . Collections . Generic ;
3+ using System . Threading ;
34using System . Threading . Tasks ;
45
56using Avalonia . Threading ;
@@ -10,121 +11,161 @@ namespace SourceGit.ViewModels
1011{
1112 public class Blame : ObservableObject
1213 {
13- public string Title
14+ public string FilePath
1415 {
15- get => _title ;
16- private set => SetProperty ( ref _title , value ) ;
16+ get ;
1717 }
1818
19- public bool IsBinary
19+ public Models . Commit Revision
2020 {
21- get => _data != null && _data . IsBinary ;
21+ get => _revision ;
22+ private set => SetProperty ( ref _revision , value ) ;
2223 }
2324
24- public bool CanMoveBack
25+ public Models . BlameData Data
2526 {
26- get => _shaHistoryIndex > 0 && _shaHistory . Count > 1 ;
27+ get => _data ;
28+ private set
29+ {
30+ if ( SetProperty ( ref _data , value ) )
31+ OnPropertyChanged ( nameof ( IsBinary ) ) ;
32+ }
2733 }
28- public bool CanMoveForward
34+
35+ public bool IsBinary
2936 {
30- get => _shaHistoryIndex < _shaHistory . Count - 1 ;
37+ get => _data != null && _data . IsBinary ;
3138 }
3239
33- public Models . BlameData Data
40+ public bool CanBack
3441 {
35- get => _data ;
36- private set => SetProperty ( ref _data , value ) ;
42+ get => _navigationActiveIndex > 0 ;
3743 }
3844
39- public Blame ( string repo , string file , string revision )
45+ public bool CanForward
4046 {
41- _repo = repo ;
42- _file = file ;
43-
44- SetBlameData ( $ "{ revision . AsSpan ( 0 , 10 ) } ", true ) ;
47+ get => _navigationActiveIndex < _navigationHistory . Count - 1 ;
4548 }
4649
47- private void SetBlameData ( string commitSHA , bool resetHistoryForward )
50+ public Blame ( string repo , string file , Models . Commit commit )
4851 {
49- Title = $ " { _file } @ { commitSHA } " ;
52+ var sha = commit . SHA . Substring ( 0 , 10 ) ;
5053
51- Task . Run ( ( ) =>
52- {
53- var result = new Commands . Blame ( _repo , _file , commitSHA ) . Result ( ) ;
54- Dispatcher . UIThread . Invoke ( ( ) =>
55- {
56- Data = result ;
57- OnPropertyChanged ( nameof ( IsBinary ) ) ;
58- } ) ;
59- } ) ;
54+ FilePath = file ;
55+ Revision = commit ;
6056
61- if ( resetHistoryForward )
62- {
63- if ( _shaHistoryIndex < _shaHistory . Count - 1 )
64- _shaHistory . RemoveRange ( _shaHistoryIndex + 1 , _shaHistory . Count - _shaHistoryIndex - 1 ) ;
57+ _repo = repo ;
58+ _navigationHistory . Add ( sha ) ;
59+ _commits . Add ( sha , commit ) ;
60+ SetBlameData ( sha ) ;
61+ }
6562
66- if ( _shaHistory . Count == 0 || _shaHistory [ _shaHistoryIndex ] != commitSHA )
67- {
68- _shaHistory . Add ( commitSHA ) ;
69- _shaHistoryIndex = _shaHistory . Count - 1 ;
70- }
71- }
63+ public string GetCommitMessage ( string sha )
64+ {
65+ if ( _commitMessages . TryGetValue ( sha , out var msg ) )
66+ return msg ;
7267
73- OnPropertyChanged ( nameof ( CanMoveBack ) ) ;
74- OnPropertyChanged ( nameof ( CanMoveForward ) ) ;
68+ msg = new Commands . QueryCommitFullMessage ( _repo , sha ) . Result ( ) ;
69+ _commitMessages [ sha ] = msg ;
70+ return msg ;
7571 }
7672
7773 public void Back ( )
7874 {
79- -- _shaHistoryIndex ;
80- if ( _shaHistoryIndex < 0 )
81- _shaHistoryIndex = 0 ;
75+ if ( _navigationActiveIndex <= 0 )
76+ return ;
8277
83- NavigateToCommit ( _shaHistory [ _shaHistoryIndex ] , false ) ;
78+ _navigationActiveIndex -- ;
79+ OnPropertyChanged ( nameof ( CanBack ) ) ;
80+ OnPropertyChanged ( nameof ( CanForward ) ) ;
81+ NavigateToCommit ( _navigationHistory [ _navigationActiveIndex ] ) ;
8482 }
8583
8684 public void Forward ( )
8785 {
88- ++ _shaHistoryIndex ;
89- if ( _shaHistoryIndex >= _shaHistory . Count )
90- _shaHistoryIndex = _shaHistory . Count - 1 ;
86+ if ( _navigationActiveIndex >= _navigationHistory . Count - 1 )
87+ return ;
9188
92- NavigateToCommit ( _shaHistory [ _shaHistoryIndex ] , false ) ;
89+ _navigationActiveIndex ++ ;
90+ OnPropertyChanged ( nameof ( CanBack ) ) ;
91+ OnPropertyChanged ( nameof ( CanForward ) ) ;
92+ NavigateToCommit ( _navigationHistory [ _navigationActiveIndex ] ) ;
9393 }
9494
95- public void NavigateToCommit ( string commitSHA , bool resetHistoryForward )
95+ public void NavigateToCommit ( string commitSHA )
9696 {
97- var launcher = App . GetLauncher ( ) ;
98- if ( launcher == null )
99- return ;
97+ if ( ! _navigationHistory [ _navigationActiveIndex ] . Equals ( commitSHA , StringComparison . Ordinal ) )
98+ {
99+ _navigationHistory . Add ( commitSHA ) ;
100+ _navigationActiveIndex = _navigationHistory . Count - 1 ;
101+ OnPropertyChanged ( nameof ( CanBack ) ) ;
102+ OnPropertyChanged ( nameof ( CanForward ) ) ;
103+ }
104+
105+ if ( ! Revision . SHA . StartsWith ( commitSHA , StringComparison . Ordinal ) )
106+ SetBlameData ( commitSHA ) ;
100107
101- foreach ( var page in launcher . Pages )
108+ if ( App . GetLauncher ( ) is { Pages : { } pages } )
102109 {
103- if ( page . Data is Repository repo && repo . FullPath . Equals ( _repo ) )
110+ foreach ( var page in pages )
104111 {
105- repo . NavigateToCommit ( commitSHA ) ;
106- SetBlameData ( commitSHA , resetHistoryForward ) ;
107- break ;
112+ if ( page . Data is Repository repo && repo . FullPath . Equals ( _repo ) )
113+ {
114+ repo . NavigateToCommit ( commitSHA ) ;
115+ break ;
116+ }
108117 }
109- }
118+ }
110119 }
111120
112- public string GetCommitMessage ( string sha )
121+ private void SetBlameData ( string commitSHA )
113122 {
114- if ( _commitMessages . TryGetValue ( sha , out var msg ) )
115- return msg ;
123+ if ( _cancellationSource is { IsCancellationRequested : false } )
124+ _cancellationSource . Cancel ( ) ;
116125
117- msg = new Commands . QueryCommitFullMessage ( _repo , sha ) . Result ( ) ;
118- _commitMessages [ sha ] = msg ;
119- return msg ;
126+ _cancellationSource = new CancellationTokenSource ( ) ;
127+ var token = _cancellationSource . Token ;
128+
129+ if ( _commits . TryGetValue ( commitSHA , out var c ) )
130+ {
131+ Revision = c ;
132+ }
133+ else
134+ {
135+ Task . Run ( ( ) =>
136+ {
137+ var result = new Commands . QuerySingleCommit ( _repo , commitSHA ) . Result ( ) ;
138+
139+ Dispatcher . UIThread . Invoke ( ( ) =>
140+ {
141+ if ( ! token . IsCancellationRequested )
142+ {
143+ _commits . Add ( commitSHA , result ) ;
144+ Revision = result ?? new Models . Commit ( ) { SHA = commitSHA } ;
145+ }
146+ } ) ;
147+ } , token ) ;
148+ }
149+
150+ Task . Run ( ( ) =>
151+ {
152+ var result = new Commands . Blame ( _repo , FilePath , commitSHA ) . Result ( ) ;
153+
154+ Dispatcher . UIThread . Invoke ( ( ) =>
155+ {
156+ if ( ! token . IsCancellationRequested )
157+ Data = result ;
158+ } ) ;
159+ } , token ) ;
120160 }
121161
122162 private string _repo ;
123- private string _file ;
124- private string _title ;
125- private int _shaHistoryIndex = 0 ;
126- private List < string > _shaHistory = [ ] ;
163+ private Models . Commit _revision ;
164+ private CancellationTokenSource _cancellationSource = null ;
165+ private int _navigationActiveIndex = 0 ;
166+ private List < string > _navigationHistory = [ ] ;
127167 private Models . BlameData _data = null ;
128- private Dictionary < string , string > _commitMessages = new Dictionary < string , string > ( ) ;
168+ private Dictionary < string , Models . Commit > _commits = new ( ) ;
169+ private Dictionary < string , string > _commitMessages = new ( ) ;
129170 }
130171}
0 commit comments