1
1
using System ;
2
2
using System . Collections . Generic ;
3
+ using System . Threading ;
3
4
using System . Threading . Tasks ;
4
5
5
6
using Avalonia . Threading ;
@@ -10,121 +11,161 @@ namespace SourceGit.ViewModels
10
11
{
11
12
public class Blame : ObservableObject
12
13
{
13
- public string Title
14
+ public string FilePath
14
15
{
15
- get => _title ;
16
- private set => SetProperty ( ref _title , value ) ;
16
+ get ;
17
17
}
18
18
19
- public bool IsBinary
19
+ public Models . Commit Revision
20
20
{
21
- get => _data != null && _data . IsBinary ;
21
+ get => _revision ;
22
+ private set => SetProperty ( ref _revision , value ) ;
22
23
}
23
24
24
- public bool CanMoveBack
25
+ public Models . BlameData Data
25
26
{
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
+ }
27
33
}
28
- public bool CanMoveForward
34
+
35
+ public bool IsBinary
29
36
{
30
- get => _shaHistoryIndex < _shaHistory . Count - 1 ;
37
+ get => _data != null && _data . IsBinary ;
31
38
}
32
39
33
- public Models . BlameData Data
40
+ public bool CanBack
34
41
{
35
- get => _data ;
36
- private set => SetProperty ( ref _data , value ) ;
42
+ get => _navigationActiveIndex > 0 ;
37
43
}
38
44
39
- public Blame ( string repo , string file , string revision )
45
+ public bool CanForward
40
46
{
41
- _repo = repo ;
42
- _file = file ;
43
-
44
- SetBlameData ( $ "{ revision . AsSpan ( 0 , 10 ) } ", true ) ;
47
+ get => _navigationActiveIndex < _navigationHistory . Count - 1 ;
45
48
}
46
49
47
- private void SetBlameData ( string commitSHA , bool resetHistoryForward )
50
+ public Blame ( string repo , string file , Models . Commit commit )
48
51
{
49
- Title = $ " { _file } @ { commitSHA } " ;
52
+ var sha = commit . SHA . Substring ( 0 , 10 ) ;
50
53
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 ;
60
56
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
+ }
65
62
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 ;
72
67
73
- OnPropertyChanged ( nameof ( CanMoveBack ) ) ;
74
- OnPropertyChanged ( nameof ( CanMoveForward ) ) ;
68
+ msg = new Commands . QueryCommitFullMessage ( _repo , sha ) . Result ( ) ;
69
+ _commitMessages [ sha ] = msg ;
70
+ return msg ;
75
71
}
76
72
77
73
public void Back ( )
78
74
{
79
- -- _shaHistoryIndex ;
80
- if ( _shaHistoryIndex < 0 )
81
- _shaHistoryIndex = 0 ;
75
+ if ( _navigationActiveIndex <= 0 )
76
+ return ;
82
77
83
- NavigateToCommit ( _shaHistory [ _shaHistoryIndex ] , false ) ;
78
+ _navigationActiveIndex -- ;
79
+ OnPropertyChanged ( nameof ( CanBack ) ) ;
80
+ OnPropertyChanged ( nameof ( CanForward ) ) ;
81
+ NavigateToCommit ( _navigationHistory [ _navigationActiveIndex ] ) ;
84
82
}
85
83
86
84
public void Forward ( )
87
85
{
88
- ++ _shaHistoryIndex ;
89
- if ( _shaHistoryIndex >= _shaHistory . Count )
90
- _shaHistoryIndex = _shaHistory . Count - 1 ;
86
+ if ( _navigationActiveIndex >= _navigationHistory . Count - 1 )
87
+ return ;
91
88
92
- NavigateToCommit ( _shaHistory [ _shaHistoryIndex ] , false ) ;
89
+ _navigationActiveIndex ++ ;
90
+ OnPropertyChanged ( nameof ( CanBack ) ) ;
91
+ OnPropertyChanged ( nameof ( CanForward ) ) ;
92
+ NavigateToCommit ( _navigationHistory [ _navigationActiveIndex ] ) ;
93
93
}
94
94
95
- public void NavigateToCommit ( string commitSHA , bool resetHistoryForward )
95
+ public void NavigateToCommit ( string commitSHA )
96
96
{
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 ) ;
100
107
101
- foreach ( var page in launcher . Pages )
108
+ if ( App . GetLauncher ( ) is { Pages : { } pages } )
102
109
{
103
- if ( page . Data is Repository repo && repo . FullPath . Equals ( _repo ) )
110
+ foreach ( var page in pages )
104
111
{
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
+ }
108
117
}
109
- }
118
+ }
110
119
}
111
120
112
- public string GetCommitMessage ( string sha )
121
+ private void SetBlameData ( string commitSHA )
113
122
{
114
- if ( _commitMessages . TryGetValue ( sha , out var msg ) )
115
- return msg ;
123
+ if ( _cancellationSource is { IsCancellationRequested : false } )
124
+ _cancellationSource . Cancel ( ) ;
116
125
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 ) ;
120
160
}
121
161
122
162
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 = [ ] ;
127
167
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 ( ) ;
129
170
}
130
171
}
0 commit comments