Integrate existing code with TorStatusChecker
That is based on PeriodicRunner.
DELETE
WalletWasabi.Fluent/AppServices/Tor/StatusChecker.cs
-using System.Collections.Generic;
-using System.Reactive.Concurrency;
-using System.Reactive.Linq;
-using WalletWasabi.Services.Tor.StatusChecker;
-
-namespace WalletWasabi.Fluent.AppServices.Tor;
-
-public class StatusChecker
-{
- public StatusChecker(TorNetwork reporter, TimeSpan checkInterval, IScheduler scheduler)
- {
- var timer = Observable.Timer(checkInterval, scheduler).SelectMany(x => reporter.Issues.ToList());
- var initial = Observable.Defer(() => reporter.Issues.ToList());
-
- Issues =
- initial.Concat(timer)
- .Retry();
- }
-
- public IObservable<IList<Issue>> Issues { get; }
-}

ADD
WalletWasabi.Fluent/AppServices/Tor/StatusCheckerWrapper.cs
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive.Linq;
+using WalletWasabi.Services;
+using WalletWasabi.Services.Tor.StatusChecker;
+
+namespace WalletWasabi.Fluent.AppServices.Tor;
+
+public class StatusCheckerWrapper
+{
+ public StatusCheckerWrapper(TorStatusChecker statusChecker)
+ {
+ Issues = Observable
+ .FromEventPattern<Issue[]>(statusChecker, nameof(TorStatusChecker.StatusEvent))
+ .Select(pattern => pattern.EventArgs.ToList());
+ }
+
+ public IObservable<IList<Issue>> Issues { get; }
+}

DELETE
WalletWasabi.Fluent/AppServices/Tor/TorNetwork.cs
-using System.Reactive.Linq;
-using WalletWasabi.Fluent.ViewModels.StatusIcon;
-using WalletWasabi.Services.Tor.StatusChecker;
-
-namespace WalletWasabi.Fluent.AppServices.Tor;
-
-public class TorNetwork
-{
- private static readonly Uri RssFeedUri = new("https://status.torproject.org/index.xml");
-
- public TorNetwork(HttpGetStringReader httpGetReader, XmlIssueListParser issueListParser)
- {
- var observable = Observable
- .FromAsync(() => httpGetReader.ReadAsync(RssFeedUri))
- .SelectMany(content => issueListParser.Parse(content).ToObservable());
- Issues = observable;
- }
-
- public IObservable<Issue> Issues { get; }
-}

MODIFY
WalletWasabi.Fluent/Global.cs
WalletWasabi.Fluent/Global.cs
@@ -22,6 +22,7 @@ using WalletWasabi.Services;
using WalletWasabi.Services.Terminate;
using WalletWasabi.Stores;
using WalletWasabi.Rpc;
+using WalletWasabi.Services.Tor.StatusChecker;
using WalletWasabi.Tor;
using WalletWasabi.Tor.Socks5.Pool.Circuits;
using WalletWasabi.WabiSabi.Client;
@@ -52,6 +53,7 @@ public class Global
public CoinJoinProcessor? CoinJoinProcessor { get; set; }
private TorProcessManager? TorManager { get; set; }
public CoreNode? BitcoinCoreNode { get; private set; }
+ public TorStatusChecker TorStatusChecker { get; set; }
public HostedServices HostedServices { get; }
public UiConfig UiConfig { get; }
@@ -98,6 +100,7 @@ public class Global
Synchronizer = new WasabiSynchronizer(BitcoinStore, HttpClientFactory);
LegalChecker = new(DataDir);
TransactionBroadcaster = new TransactionBroadcaster(Network, BitcoinStore, HttpClientFactory, WalletManager);
+ TorStatusChecker = new TorStatusChecker(TimeSpan.FromHours(5), HttpClientFactory.NewHttpClient(Mode.DefaultCircuit), new XmlIssueListParser());
RoundStateUpdaterCircuit = new PersonCircuit();
@@ -109,6 +112,8 @@ public class Global
}
}
+
+
/// <remarks>Use this variable as a guard to prevent touching <see cref="StoppingCts"/> that might have already been disposed.</remarks>
private volatile bool _disposeRequested;
@@ -137,6 +142,7 @@ public class Global
var bstoreInitTask = BitcoinStore.InitializeAsync(cancel);
HostedServices.Register<UpdateChecker>(() => new UpdateChecker(TimeSpan.FromMinutes(7), Synchronizer), "Software Update Checker");
+ HostedServices.Register<TorStatusChecker>(() => TorStatusChecker, "Tor Network Checker");
await LegalChecker.InitializeAsync(HostedServices.Get<UpdateChecker>()).ConfigureAwait(false);
cancel.ThrowIfCancellationRequested();

MODIFY
WalletWasabi.Fluent/Services.cs
WalletWasabi.Fluent/Services.cs
@@ -34,8 +34,11 @@ public static class Services
public static SingleInstanceChecker SingleInstanceChecker { get; private set; } = null!;
+ public static TorStatusChecker TorStatusChecker { get; private set; } = null!;
+
public static bool IsInitialized { get; private set; }
+
/// <summary>
/// Initializes global services used by fluent project.
/// </summary>
@@ -66,6 +69,7 @@ public static class Services
HostedServices = global.HostedServices;
UiConfig = global.UiConfig;
SingleInstanceChecker = singleInstanceChecker;
+ TorStatusChecker = global.TorStatusChecker;
IsInitialized = true;
}

MODIFY
WalletWasabi.Fluent/ViewModels/MainViewModel.cs
WalletWasabi.Fluent/ViewModels/MainViewModel.cs
@@ -17,8 +17,6 @@ using WalletWasabi.Fluent.ViewModels.Settings;
using WalletWasabi.Fluent.ViewModels.StatusIcon;
using WalletWasabi.Fluent.ViewModels.TransactionBroadcasting;
using WalletWasabi.Fluent.ViewModels.Wallets;
-using WalletWasabi.Services.Tor.StatusChecker;
-using WalletWasabi.Tor.Socks5.Pool.Circuits;
namespace WalletWasabi.Fluent.ViewModels;
@@ -60,7 +58,7 @@ public partial class MainViewModel : ViewModelBase
UiServices.Initialize();
- _statusIcon = new StatusIconViewModel(CreateTorStatusChecker());
+ _statusIcon = new StatusIconViewModel(new StatusCheckerWrapper(Services.TorStatusChecker));
_addWalletPage = new AddWalletPageViewModel();
_settingsPage = new SettingsPageViewModel();
@@ -156,14 +154,6 @@ public partial class MainViewModel : ViewModelBase
SearchBar = new SearchBarViewModel(source.Changes);
}
- private static StatusChecker CreateTorStatusChecker()
- {
- var httpClient = Services.HttpClientFactory.NewHttpClient(Mode.DefaultCircuit);
- var torNetwork = new TorNetwork(new HttpGetStringReader(httpClient), new XmlIssueListParser());
- var statusChecker = new StatusChecker(torNetwork, TimeSpan.FromHours(6), new NewThreadScheduler());
- return statusChecker;
- }
-
public IObservable<WalletViewModel> CurrentWallet { get; }
public TargettedNavigationStack MainScreen { get; }

DELETE
WalletWasabi.Fluent/ViewModels/StatusIcon/HttpGetStringReader.cs
-using System.Net.Http;
-using System.Threading.Tasks;
-using WalletWasabi.Tor.Http;
-
-namespace WalletWasabi.Fluent.ViewModels.StatusIcon;
-
-public class HttpGetStringReader
-{
- private readonly IHttpClient _httpClient;
-
- public HttpGetStringReader(IHttpClient httpClient)
- {
- _httpClient = httpClient;
- }
-
- public async Task<string> ReadAsync(Uri uri)
- {
- using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
- var response = await _httpClient.SendAsync(httpRequestMessage).ConfigureAwait(false);
- var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
- return content;
- }
-}

MODIFY
WalletWasabi.Fluent/ViewModels/StatusIcon/StatusIconViewModel.cs
WalletWasabi.Fluent/ViewModels/StatusIcon/StatusIconViewModel.cs
@@ -31,7 +31,7 @@ public partial class StatusIconViewModel : IStatusIconViewModel, IDisposable
[AutoNotify] private string? _versionText;
private readonly ObservableAsPropertyHelper<ICollection<Issue>> _torIssues;
- public StatusIconViewModel(StatusChecker statusChecker)
+ public StatusIconViewModel(StatusCheckerWrapper statusCheckerWrapper)
{
UseTor = Services.Config.UseTor; // Do not make it dynamic, because if you change this config settings only next time will it activate.
TorStatus = UseTor ? Services.Synchronizer.TorStatus : TorStatus.TurnedOff;
@@ -61,7 +61,7 @@ public partial class StatusIconViewModel : IStatusIconViewModel, IDisposable
SetStatusIconState();
});
- var issues = statusChecker.Issues
+ var issues = statusCheckerWrapper.Issues
.Select(r => r.Where(issue => !issue.Resolved).ToList())
.ObserveOn(RxApp.MainThreadScheduler)
.Publish();

Integrate existing code with TorStatusChecker

That is based on PeriodicRunner.