1717// DEALINGS IN THE SOFTWARE.
1818
1919using System ;
20- using System . ComponentModel ;
2120using System . IO ;
22- using System . Linq ;
23- using System . Net . Http ;
2421using System . Text . RegularExpressions ;
25- using System . Threading . Tasks ;
2622using System . Windows ;
2723using System . Windows . Controls ;
2824using System . Windows . Data ;
2925using System . Windows . Input ;
3026using System . Windows . Navigation ;
31- using System . Xml . Linq ;
3227
3328using ICSharpCode . AvalonEdit . Rendering ;
3429using ICSharpCode . Decompiler ;
3530using ICSharpCode . ILSpy . Properties ;
3631using ICSharpCode . ILSpy . TextView ;
3732using ICSharpCode . ILSpy . Themes ;
33+ using ICSharpCode . ILSpy . Updates ;
3834using ICSharpCode . ILSpyX . Settings ;
3935
4036namespace ICSharpCode . ILSpy
@@ -50,11 +46,6 @@ public override void Execute(object parameter)
5046 ) ;
5147 }
5248
53- static readonly Uri UpdateUrl = new Uri ( "https://ilspy.net/updates.xml" ) ;
54- const string band = "stable" ;
55-
56- static AvailableVersionInfo latestAvailableVersion ;
57-
5849 public static void Display ( DecompilerTextView textView )
5950 {
6051 AvalonEditTextOutput output = new AvalonEditTextOutput ( ) {
@@ -71,14 +62,14 @@ public static void Display(DecompilerTextView textView)
7162 StackPanel stackPanel = new StackPanel ( ) ;
7263 stackPanel . HorizontalAlignment = HorizontalAlignment . Center ;
7364 stackPanel . Orientation = Orientation . Horizontal ;
74- if ( latestAvailableVersion == null )
65+ if ( NotifyOfUpdatesStrategy . LatestAvailableVersion == null )
7566 {
7667 AddUpdateCheckButton ( stackPanel , textView ) ;
7768 }
7869 else
7970 {
8071 // we already retrieved the latest version sometime earlier
81- ShowAvailableVersion ( latestAvailableVersion , stackPanel ) ;
72+ ShowAvailableVersion ( NotifyOfUpdatesStrategy . LatestAvailableVersion , stackPanel ) ;
8273 }
8374 CheckBox checkBox = new CheckBox ( ) ;
8475 checkBox . Margin = new Thickness ( 4 ) ;
@@ -142,7 +133,7 @@ static void AddUpdateCheckButton(StackPanel stackPanel, DecompilerTextView textV
142133
143134 try
144135 {
145- AvailableVersionInfo vInfo = await GetLatestVersionAsync ( ) ;
136+ AvailableVersionInfo vInfo = await NotifyOfUpdatesStrategy . GetLatestVersionAsync ( ) ;
146137 stackPanel . Children . Clear ( ) ;
147138 ShowAvailableVersion ( vInfo , stackPanel ) ;
148139 }
@@ -155,11 +146,9 @@ static void AddUpdateCheckButton(StackPanel stackPanel, DecompilerTextView textV
155146 } ;
156147 }
157148
158- static readonly Version currentVersion = new Version ( DecompilerVersionInfo . Major + "." + DecompilerVersionInfo . Minor + "." + DecompilerVersionInfo . Build + "." + DecompilerVersionInfo . Revision ) ;
159-
160149 static void ShowAvailableVersion ( AvailableVersionInfo availableVersion , StackPanel stackPanel )
161150 {
162- if ( currentVersion == availableVersion . Version )
151+ if ( AppUpdateService . CurrentVersion == availableVersion . Version )
163152 {
164153 stackPanel . Children . Add (
165154 new Image {
@@ -173,7 +162,7 @@ static void ShowAvailableVersion(AvailableVersionInfo availableVersion, StackPan
173162 VerticalAlignment = VerticalAlignment . Bottom
174163 } ) ;
175164 }
176- else if ( currentVersion < availableVersion . Version )
165+ else if ( AppUpdateService . CurrentVersion < availableVersion . Version )
177166 {
178167 stackPanel . Children . Add (
179168 new TextBlock {
@@ -197,149 +186,6 @@ static void ShowAvailableVersion(AvailableVersionInfo availableVersion, StackPan
197186 stackPanel . Children . Add ( new TextBlock { Text = Resources . UsingNightlyBuildNewerThanLatestRelease } ) ;
198187 }
199188 }
200-
201- static async Task < AvailableVersionInfo > GetLatestVersionAsync ( )
202- {
203- var client = new HttpClient ( new HttpClientHandler ( ) {
204- UseProxy = true ,
205- UseDefaultCredentials = true ,
206- } ) ;
207- string data = await client . GetStringAsync ( UpdateUrl ) ;
208-
209- XDocument doc = XDocument . Load ( new StringReader ( data ) ) ;
210- var bands = doc . Root . Elements ( "band" ) ;
211- var currentBand = bands . FirstOrDefault ( b => ( string ) b . Attribute ( "id" ) == band ) ?? bands . First ( ) ;
212- Version version = new Version ( ( string ) currentBand . Element ( "latestVersion" ) ) ;
213- string url = ( string ) currentBand . Element ( "downloadUrl" ) ;
214- if ( ! ( url . StartsWith ( "http://" , StringComparison . Ordinal ) || url . StartsWith ( "https://" , StringComparison . Ordinal ) ) )
215- url = null ; // don't accept non-urls
216-
217- latestAvailableVersion = new AvailableVersionInfo { Version = version , DownloadUrl = url } ;
218- return latestAvailableVersion ;
219- }
220-
221- sealed class AvailableVersionInfo
222- {
223- public Version Version ;
224- public string DownloadUrl ;
225- }
226-
227- sealed class UpdateSettings : INotifyPropertyChanged
228- {
229- public UpdateSettings ( ILSpySettings spySettings )
230- {
231- XElement s = spySettings [ "UpdateSettings" ] ;
232- this . automaticUpdateCheckEnabled = ( bool ? ) s . Element ( "AutomaticUpdateCheckEnabled" ) ?? true ;
233- try
234- {
235- this . lastSuccessfulUpdateCheck = ( DateTime ? ) s . Element ( "LastSuccessfulUpdateCheck" ) ;
236- }
237- catch ( FormatException )
238- {
239- // avoid crashing on settings files invalid due to
240- // https://github.com/icsharpcode/ILSpy/issues/closed/#issue/2
241- }
242- }
243-
244- bool automaticUpdateCheckEnabled ;
245-
246- public bool AutomaticUpdateCheckEnabled {
247- get { return automaticUpdateCheckEnabled ; }
248- set {
249- if ( automaticUpdateCheckEnabled != value )
250- {
251- automaticUpdateCheckEnabled = value ;
252- Save ( ) ;
253- OnPropertyChanged ( nameof ( AutomaticUpdateCheckEnabled ) ) ;
254- }
255- }
256- }
257-
258- DateTime ? lastSuccessfulUpdateCheck ;
259-
260- public DateTime ? LastSuccessfulUpdateCheck {
261- get { return lastSuccessfulUpdateCheck ; }
262- set {
263- if ( lastSuccessfulUpdateCheck != value )
264- {
265- lastSuccessfulUpdateCheck = value ;
266- Save ( ) ;
267- OnPropertyChanged ( nameof ( LastSuccessfulUpdateCheck ) ) ;
268- }
269- }
270- }
271-
272- public void Save ( )
273- {
274- XElement updateSettings = new XElement ( "UpdateSettings" ) ;
275- updateSettings . Add ( new XElement ( "AutomaticUpdateCheckEnabled" , automaticUpdateCheckEnabled ) ) ;
276- if ( lastSuccessfulUpdateCheck != null )
277- updateSettings . Add ( new XElement ( "LastSuccessfulUpdateCheck" , lastSuccessfulUpdateCheck ) ) ;
278- ILSpySettings . SaveSettings ( updateSettings ) ;
279- }
280-
281- public event PropertyChangedEventHandler PropertyChanged ;
282-
283- void OnPropertyChanged ( string propertyName )
284- {
285- PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( propertyName ) ) ;
286- }
287- }
288-
289- /// <summary>
290- /// If automatic update checking is enabled, checks if there are any updates available.
291- /// Returns the download URL if an update is available.
292- /// Returns null if no update is available, or if no check was performed.
293- /// </summary>
294- public static async Task < string > CheckForUpdatesIfEnabledAsync ( ILSpySettings spySettings )
295- {
296- UpdateSettings s = new UpdateSettings ( spySettings ) ;
297-
298- // If we're in an MSIX package, updates work differently
299- if ( s . AutomaticUpdateCheckEnabled )
300- {
301- // perform update check if we never did one before;
302- // or if the last check wasn't in the past 7 days
303- if ( s . LastSuccessfulUpdateCheck == null
304- || s . LastSuccessfulUpdateCheck < DateTime . UtcNow . AddDays ( - 7 )
305- || s . LastSuccessfulUpdateCheck > DateTime . UtcNow )
306- {
307- return await CheckForUpdateInternal ( s ) ;
308- }
309- else
310- {
311- return null ;
312- }
313- }
314- else
315- {
316- return null ;
317- }
318- }
319-
320- public static Task < string > CheckForUpdatesAsync ( ILSpySettings spySettings )
321- {
322- UpdateSettings s = new UpdateSettings ( spySettings ) ;
323- return CheckForUpdateInternal ( s ) ;
324- }
325-
326- static async Task < string > CheckForUpdateInternal ( UpdateSettings s )
327- {
328- try
329- {
330- var v = await GetLatestVersionAsync ( ) ;
331- s . LastSuccessfulUpdateCheck = DateTime . UtcNow ;
332- if ( v . Version > currentVersion )
333- return v . DownloadUrl ;
334- else
335- return null ;
336- }
337- catch ( Exception )
338- {
339- // ignore errors getting the version info
340- return null ;
341- }
342- }
343189 }
344190
345191 /// <summary>
0 commit comments