Skip to content

Commit d07a5ee

Browse files
committed
feat: support click link in search detail page
1 parent d2dc408 commit d07a5ee

File tree

3 files changed

+88
-53
lines changed

3 files changed

+88
-53
lines changed

src/Services/Action/ActionService.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ public void Runner()
7171
? $"[Runner] {item} uninstall sub-task completed"
7272
: $"[Runner] {item} uninstall sub-task failed\n Reason:{result.Message}");
7373
}
74-
Log.Information($"[Runner] Task {currentAction.OperationType} Completed");
7574
break;
7675
}
7776

@@ -93,7 +92,6 @@ public void Runner()
9392
? $"[Runner] {item} install sub-task completed"
9493
: $"[Runner] {item} install sub-task failed\n Reason:{result.Message}");
9594
}
96-
Log.Information($"[Runner] Task {currentAction.OperationType} Completed");
9795
break;
9896
}
9997
case ActionType.InstallByRequirements:
@@ -108,7 +106,6 @@ public void Runner()
108106
currentAction.DetectIssue = true;
109107
consoleError.AppendLine(result.Message);
110108
}
111-
Log.Information($"[Runner] Task {currentAction.OperationType} Completed");
112109
break;
113110
}
114111
case ActionType.Download:
@@ -129,7 +126,6 @@ public void Runner()
129126
? $"[Runner] {item} download sub-task completed"
130127
: $"[Runner] {item} download sub-task failed\n Reason:{result.Message}");
131128
}
132-
Log.Information($"[Runner] Task {currentAction.OperationType} Completed");
133129
break;
134130
}
135131
case ActionType.Update:
@@ -150,12 +146,13 @@ public void Runner()
150146
? $"[Runner] {item} update sub-task completed"
151147
: $"[Runner] {item} update sub-task failed\n Reason:{result.Message}");
152148
}
153-
Log.Information($"[Runner] Task {currentAction.OperationType} Completed");
154149
break;
155150
}
156151
default:
157152
throw new ArgumentOutOfRangeException();
158153
}
154+
155+
Log.Information($"[Runner] Task {currentAction.OperationType} Completed");
159156
currentAction.CompletedSubTaskNumber = currentAction.TotalSubTaskNumber;
160157
currentAction.OperationStatus = "Completed";
161158
if (errorDetection)

src/ViewModels/Pages/Search/SearchDetailViewModel.cs

Lines changed: 68 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -129,58 +129,81 @@ private void Receive(object recipient, SearchDetailMessage message)
129129
{
130130
Package = message.Package;
131131

132-
SearchDetailPage.ProjectDescriptionWebView!.Loaded += async (_, _) =>
132+
SearchDetailPage.ProjectDescriptionWebView!.Loaded += async (_, _) => await LoadPackageDetailsAsync(message);
133+
}
134+
135+
private async Task LoadPackageDetailsAsync(SearchDetailMessage message)
136+
{
137+
try
133138
{
134139
ProjectDescriptionVisibility = false;
135-
var packageVersions = await _environmentService.GetVersions(Package!.Name, new CancellationToken(), Configuration.AppConfig!.PackageSource.AllowNonRelease);
136-
switch (packageVersions.Status)
137-
{
138-
case 1 or 2:
139-
_toastService.Error(Lang.SearchDetail_Exception_NetworkError);
140-
await Task.Delay(1000);
141-
_navigationService.GoBack();
142-
return;
143-
144-
default:
145-
AvailableVersions = new ObservableCollection<string>(packageVersions.Versions!.Reverse());
146-
TargetVersion = AvailableVersions.First();
147-
break;
148-
}
149-
await CoreWebView2Environment.CreateAsync(null, AppInfo.CachesDir);
150-
await SearchDetailPage.ProjectDescriptionWebView.EnsureCoreWebView2Async().ConfigureAwait(true);
151-
try
152-
{
153-
var projectDescriptionUrl = message.Package.Url;
154-
var html = await _httpClient.GetStringAsync(projectDescriptionUrl);
155-
var htmlDocument = new HtmlDocument();
156-
htmlDocument.LoadHtml(html);
157-
string projectDescriptionHtml = string.Format(HtmlModel, _themeType, ThemeTypeInHex, htmlDocument.DocumentNode.SelectSingleNode("//*[@id=\"description\"]/div").InnerHtml);
158-
159-
SearchDetailPage.ProjectDescriptionWebView.CoreWebView2.Profile.PreferredColorScheme = CoreWebView2PreferredColorScheme.Dark;
160-
SearchDetailPage.ProjectDescriptionWebView.NavigateToString(projectDescriptionHtml);
161-
}
162-
catch (Exception ex)
163-
{
164-
Log.Error(ex.Message);
165-
_toastService.Error(Lang.SearchDetail_ProjectDescription_LoadFailed);
166-
string projectDescriptionHtml = string.Format(HtmlModel, _themeType, ThemeTypeInHex, $"<p>{Lang.SearchDetail_ProjectDescription_LoadFailed}</p>");
167-
168-
SearchDetailPage.ProjectDescriptionWebView.CoreWebView2.Profile.PreferredColorScheme = CoreWebView2PreferredColorScheme.Dark;
169-
SearchDetailPage.ProjectDescriptionWebView.NavigateToString(projectDescriptionHtml);
170-
}
171-
finally
172-
{
173-
await Task.Delay(500);
174-
ProjectDescriptionVisibility = true;
175-
}
176-
};
140+
await SetupWebViewAsync(message.Package);
141+
}
142+
catch (Exception ex)
143+
{
144+
HandleLoadingError(ex);
145+
}
146+
finally
147+
{
148+
await Task.Delay(500);
149+
ProjectDescriptionVisibility = true;
150+
}
177151
}
178152

179-
public Task OnNavigatedToAsync()
153+
private async Task SetupWebViewAsync(QueryListItemModel package)
154+
{
155+
var packageVersions = await _environmentService.GetVersions(package.Name, new CancellationToken(), Configuration.AppConfig!.PackageSource.AllowNonRelease);
156+
if (packageVersions.Status is 1 or 2)
157+
{
158+
_toastService.Error(Lang.SearchDetail_Exception_NetworkError);
159+
await Task.Delay(1000);
160+
_navigationService.GoBack();
161+
return;
162+
}
163+
164+
AvailableVersions = new ObservableCollection<string>(packageVersions.Versions!.Reverse());
165+
TargetVersion = AvailableVersions.First();
166+
167+
await CoreWebView2Environment.CreateAsync(null, AppInfo.CachesDir);
168+
await SearchDetailPage.ProjectDescriptionWebView!.EnsureCoreWebView2Async().ConfigureAwait(true);
169+
await LoadProjectDescriptionAsync(package.Url);
170+
}
171+
172+
private async Task LoadProjectDescriptionAsync(string projectDescriptionUrl)
173+
{
174+
try
175+
{
176+
var html = await _httpClient.GetStringAsync(projectDescriptionUrl);
177+
var htmlDocument = new HtmlDocument();
178+
htmlDocument.LoadHtml(html);
179+
string projectDescriptionHtml = string.Format(HtmlModel, _themeType, ThemeTypeInHex, htmlDocument.DocumentNode.SelectSingleNode("//*[@id=\"description\"]/div").InnerHtml);
180+
181+
SearchDetailPage.ProjectDescriptionWebView!.CoreWebView2.Profile.PreferredColorScheme = CoreWebView2PreferredColorScheme.Dark;
182+
SearchDetailPage.ProjectDescriptionWebView.NavigateToString(projectDescriptionHtml);
183+
}
184+
catch (Exception ex)
185+
{
186+
HandleLoadingError(ex);
187+
}
188+
}
189+
190+
private void HandleLoadingError(Exception ex)
191+
{
192+
Log.Error(ex.Message);
193+
_toastService.Error(Lang.SearchDetail_ProjectDescription_LoadFailed);
194+
string projectDescriptionHtml = string.Format(HtmlModel, _themeType, ThemeTypeInHex, $"<p>{Lang.SearchDetail_ProjectDescription_LoadFailed}</p>");
195+
SearchDetailPage.ProjectDescriptionWebView!.CoreWebView2.Profile.PreferredColorScheme = CoreWebView2PreferredColorScheme.Dark;
196+
SearchDetailPage.ProjectDescriptionWebView.NavigateToString(projectDescriptionHtml);
197+
}
198+
199+
public async Task OnNavigatedToAsync()
180200
{
181201
if (!_isInitialized)
182202
InitializeViewModel();
183-
_navigationService.GetNavigationControl().BreadcrumbBar!.Visibility = Visibility.Collapsed;
203+
await Application.Current.Dispatcher.InvokeAsync(() =>
204+
{
205+
_navigationService.GetNavigationControl().BreadcrumbBar!.Visibility = Visibility.Collapsed;
206+
});
184207
switch (_themeService.GetTheme())
185208
{
186209
case ApplicationTheme.Light:
@@ -200,7 +223,6 @@ public Task OnNavigatedToAsync()
200223
throw new ArgumentOutOfRangeException();
201224
}
202225
SearchDetailPage.ProjectDescriptionWebView!.DefaultBackgroundColor = Color.FromArgb(_themeTypeInInteger);
203-
return Task.CompletedTask;
204226
}
205227

206228
public Task OnNavigatedFromAsync()

src/Views/Pages/Search/SearchDetailPage.xaml.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
using Microsoft.Web.WebView2.Core;
1+
using System.Diagnostics;
2+
using Microsoft.Web.WebView2.Core;
23
using Microsoft.Web.WebView2.Wpf;
4+
using Serilog;
35
using Wpf.Ui.Abstractions.Controls;
46
using SearchDetailViewModel = PipManager.Windows.ViewModels.Pages.Search.SearchDetailViewModel;
57

@@ -21,9 +23,23 @@ public SearchDetailPage(SearchDetailViewModel viewModel)
2123

2224
private void SearchDetailProjectDescriptionWebView_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
2325
{
24-
if (e.Uri.StartsWith("http://") || e.Uri.StartsWith("https://"))
26+
var uri = e.Uri;
27+
if (uri.StartsWith("http://") || uri.StartsWith("https://"))
2528
{
2629
e.Cancel = true;
30+
31+
try
32+
{
33+
Process.Start(new ProcessStartInfo
34+
{
35+
FileName = uri,
36+
UseShellExecute = true
37+
});
38+
}
39+
catch (Exception ex)
40+
{
41+
Log.Error("Failed to open link in external browser: " + ex.Message);
42+
}
2743
}
2844
}
2945

0 commit comments

Comments
 (0)