11using System ;
2+ using System . Diagnostics ;
23using System . Diagnostics . CodeAnalysis ;
34using System . IO ;
45using System . Linq ;
56using System . Net ;
7+ using System . Net . Http ;
68using System . Threading . Tasks ;
79using Avalonia ;
810using Avalonia . Controls ;
11+ using Avalonia . Controls . Notifications ;
912using Avalonia . Media ;
1013using Avalonia . Media . Imaging ;
1114using Avalonia . Threading ;
1619using Core . Services . MQTT ;
1720using Core . Services . Onnx ;
1821using Core . Services . Plugin ;
22+ using Core . Utils ;
1923using Core . ViewModel . Main ;
2024using Core . ViewModel . Pages ;
2125using Core . ViewModel . Pages . customScenario ;
@@ -165,6 +169,7 @@ private static IServiceProvider ConfigureServices()
165169
166170
167171 services . AddSingleton < SettingPage > ( e => new SettingPage ( ) ) ;
172+ services . AddSingleton < GitHubUpdateService > ( ) ;
168173
169174 return services . BuildServiceProvider ( ) ;
170175 }
@@ -181,28 +186,107 @@ private static void CheckAndDeleteLogFiles()
181186 var currentDate = DateTime . Today ;
182187
183188 // 获取目录下的所有日志文件,按照最后修改时间排序
184- var logFiles = Directory . EnumerateFiles ( logDirectory )
185- . Select ( f => new FileInfo ( f ) )
186- . OrderByDescending ( f => f . LastWriteTime ) ;
187-
188- // 遍历每个日志文件
189- foreach ( var logFile in logFiles )
190- // 计算日志文件的最后修改时间和当前日期的差值
191- // 如果差值大于要保留的时间范围,就删除该日志文件
192- if ( currentDate - logFile . LastWriteTime > timeSpan )
189+ try
190+ {
191+ var logFiles = Directory . EnumerateFiles ( logDirectory )
192+ . Select ( f => new FileInfo ( f ) )
193+ . OrderByDescending ( f => f . LastWriteTime ) ;
194+
195+ // 遍历每个日志文件
196+ foreach ( var logFile in logFiles )
197+ // 计算日志文件的最后修改时间和当前日期的差值
198+ // 如果差值大于要保留的时间范围,就删除该日志文件
199+ if ( currentDate - logFile . LastWriteTime > timeSpan )
200+ {
201+ Log . Debug ( $ "删除日志文件:{ logFile . FullName } ") ;
202+ logFile . Delete ( ) ;
203+ }
204+ }
205+ catch ( Exception e )
206+ {
207+ // ignored
208+ }
209+ }
210+
211+ private static async Task CheckUpdates ( )
212+ {
213+ var gitHubUpdateService = ServiceManager . Services . GetService < GitHubUpdateService > ( ) ;
214+ var ( hasUpdate , latestVersion , downloadUrl , releaseNotes ) = await gitHubUpdateService ! . CheckForUpdatesAsync ( ) ;
215+ if ( hasUpdate && ! string . IsNullOrEmpty ( downloadUrl ) )
216+ {
217+ Log . Information ( $ "发现新版本:{ latestVersion } ") ;
218+ var dialog = new DialogContent ( )
193219 {
194- Log . Debug ( $ "删除日志文件:{ logFile . FullName } ") ;
195- logFile . Delete ( ) ;
196- }
220+ Title = $ "Kitopia更新 - 发现新版本 { latestVersion } ",
221+ Content = $ "发现新版本 { latestVersion } ,是否前往下载?\n \n 更新内容:\n { releaseNotes ?? "无更新说明" } ",
222+ PrimaryButtonText = "下载并更新" ,
223+ SecondaryButtonText = "取消" ,
224+ PrimaryAction = async ( ) =>
225+ {
226+ try
227+ {
228+ var toastService = ServiceManager . Services . GetService < IToastService > ( ) ;
229+ var tempPath = Path . Combine ( Path . GetTempPath ( ) , $ "Kitopia_{ latestVersion } _Installer.exe") ;
230+
231+ using var client = new HttpClient ( ) ;
232+ using var response = await client . GetAsync ( downloadUrl , HttpCompletionOption . ResponseHeadersRead ) ;
233+ response . EnsureSuccessStatusCode ( ) ;
234+
235+ var totalBytes = response . Content . Headers . ContentLength ?? - 1L ;
236+ var canReportProgress = totalBytes != - 1 ;
237+
238+ await using var contentStream = await response . Content . ReadAsStreamAsync ( ) ;
239+ var fileStream = new FileStream ( tempPath , FileMode . Create , FileAccess . Write , FileShare . None , 8192 , true ) ;
240+
241+ var buffer = new byte [ 8192 ] ;
242+ long totalRead = 0 ;
243+ int bytesRead ;
244+ var lastProgress = - 1 ;
245+
246+ toastService ! . Show ( "更新" , "开始下载更新..." ) ;
247+
248+ while ( ( bytesRead = await contentStream . ReadAsync ( buffer , 0 , buffer . Length ) ) > 0 )
249+ {
250+ await fileStream . WriteAsync ( buffer , 0 , bytesRead ) ;
251+ totalRead += bytesRead ;
252+
253+ if ( canReportProgress )
254+ {
255+ var progress = ( int ) ( ( double ) totalRead / totalBytes * 100 ) ;
256+ if ( progress > lastProgress && progress % 10 == 0 ) // Report every 10%
257+ {
258+ lastProgress = progress ;
259+ toastService . Show ( "更新" , $ "下载进度: { progress } %") ;
260+ }
261+ }
262+ }
263+ await fileStream . DisposeAsync ( ) ;
264+ toastService . Show ( "更新" , "下载完成,正在启动安装程序..." ) ;
265+ await Task . Delay ( 1000 ) ;
266+ // Close application and start installer
267+ ServiceManager . Services . GetService < ISearchItemTool > ( ) ! . OpenFile ( tempPath ) ;
268+ await Task . Delay ( 2000 ) ;
269+ Environment . Exit ( 0 ) ;
270+ }
271+ catch ( Exception ex )
272+ {
273+ Log . Error ( ex , "更新失败" ) ;
274+ ServiceManager . Services . GetService < IToastService > ( ) ! . Show ( "更新失败" , $ "下载出错: { ex . Message } ", NotificationType . Error ) ;
275+ }
276+ }
277+ } ;
278+ await ( ( IContentDialog ) ServiceManager . Services ! . GetService ( typeof ( IContentDialog ) ) ! ) . ShowDialogAsync ( null ,
279+ dialog ) ;
280+ }
197281 }
198282
199283 public static void OnStartup ( string [ ] arg )
200284 {
201285 Log . Information ( "启动" ) ;
202286 ServiceManager . Services = ConfigureServices ( ) ;
203287
204- // CheckAndDeleteLogFiles();
205-
288+ CheckAndDeleteLogFiles ( ) ;
289+ Task . Run ( CheckUpdates ) ;
206290 MqttManager . Init ( ) . GetAwaiter ( ) . GetResult ( ) ;
207291 Log . Information ( "MQTT初始化完成" ) ;
208292 HotKeyManager . Init ( ) ;
0 commit comments