MainWindowViewModel.cs 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. using DynamicData;
  2. using DynamicData.Binding;
  3. using NatTypeTester.Models;
  4. using ReactiveUI;
  5. using STUN.Utils;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.IO;
  9. using System.Linq;
  10. using System.Reactive.Linq;
  11. namespace NatTypeTester.ViewModels
  12. {
  13. public class MainWindowViewModel : ReactiveObject, IScreen
  14. {
  15. public RoutingState Router { get; } = new();
  16. public Config Config { get; }
  17. private readonly IEnumerable<string> _defaultServers = new HashSet<string>
  18. {
  19. @"stun.syncthing.net",
  20. @"stun.qq.com",
  21. @"stun.miwifi.com",
  22. @"stun.bige0.com",
  23. @"stun.stunprotocol.org"
  24. };
  25. private SourceList<string> List { get; } = new();
  26. public readonly IObservableCollection<string> StunServers = new ObservableCollectionExtended<string>();
  27. public MainWindowViewModel(Config config)
  28. {
  29. Config = config;
  30. LoadStunServer();
  31. List.Connect()
  32. .DistinctValues(x => x)
  33. .ObserveOn(RxApp.MainThreadScheduler)
  34. .Bind(StunServers)
  35. .Subscribe();
  36. }
  37. private async void LoadStunServer()
  38. {
  39. foreach (var server in _defaultServers)
  40. {
  41. List.Add(server);
  42. }
  43. Config.StunServer = _defaultServers.First();
  44. const string path = @"stun.txt";
  45. if (!File.Exists(path))
  46. {
  47. return;
  48. }
  49. using var sw = new StreamReader(path);
  50. string line;
  51. var stun = new StunServer();
  52. while ((line = await sw.ReadLineAsync()) != null)
  53. {
  54. if (!string.IsNullOrWhiteSpace(line) && stun.Parse(line))
  55. {
  56. List.Add(stun.ToString());
  57. }
  58. }
  59. }
  60. }
  61. }