| 1 | using System.Collections.ObjectModel; |
| 2 | using Microsoft.UI.Xaml; |
| 3 | using Microsoft.UI.Xaml.Controls; |
| 4 | using RblxTool.Models; |
| 5 | using RblxTool.Services; |
| 6 | |
| 7 | namespace RblxTool.Views; |
| 8 | |
| 9 | public sealed partial class GroupsPage : Page |
| 10 | { |
| 11 | private const int MaxFeedLines = 5000; |
| 12 | |
| 13 | private readonly ObservableCollection<FeedLine> _feed = new(); |
| 14 | private JobRunner? _runner; |
| 15 | private DispatcherTimer? _metricsTimer; |
| 16 | |
| 17 | public GroupsPage() |
| 18 | { |
| 19 | InitializeComponent(); |
| 20 | FeedList.ItemsSource = _feed; |
| 21 | Loaded += OnLoaded; |
| 22 | Unloaded += (_, _) => |
| 23 | { |
| 24 | _metricsTimer?.Stop(); |
| 25 | _runner?.Stop(); |
| 26 | }; |
| 27 | } |
| 28 | |
| 29 | private void OnLoaded(object sender, RoutedEventArgs e) |
| 30 | { |
| 31 | _runner = AppState.Current.CreateRunner(DispatcherQueue); |
| 32 | _runner.EventReceived += OnEvent; |
| 33 | _runner.Completed += _ => |
| 34 | { |
| 35 | StartButton.IsEnabled = true; |
| 36 | StopButton.IsEnabled = false; |
| 37 | _metricsTimer?.Stop(); |
| 38 | Append(new FeedLine(" scan finished", FeedTone.Good)); |
| 39 | }; |
| 40 | _metricsTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(750) }; |
| 41 | _metricsTimer.Tick += (_, _) => |
| 42 | RequestsText.Text = AppState.Current.Engine.Metrics().Requests.ToString("N0"); |
| 43 | } |
| 44 | |
| 45 | private void OnStart(object sender, RoutedEventArgs e) |
| 46 | { |
| 47 | if (ClaimToggle.IsOn && AppState.Current.Active is null) |
| 48 | { |
| 49 | Append(new FeedLine(" claiming needs a signed in account", FeedTone.Bad)); |
| 50 | return; |
| 51 | } |
| 52 | var request = new HuntRequest |
| 53 | { |
| 54 | Start = (ulong)Math.Max(1, StartBox.Value), |
| 55 | End = (ulong)Math.Max(1, EndBox.Value), |
| 56 | Threads = (int)Math.Max(1, ThreadsBox.Value), |
| 57 | MinMembers = (ulong)Math.Max(0, MinMembersBox.Value), |
| 58 | Enrich = EnrichToggle.IsOn, |
| 59 | RequirePublicEntry = PublicEntryToggle.IsOn, |
| 60 | Claim = ClaimToggle.IsOn, |
| 61 | }; |
| 62 | _feed.Clear(); |
| 63 | Append(new FeedLine($" scanning groups {request.Start}..{request.End}", FeedTone.Accent)); |
| 64 | var jobId = AppState.Current.Engine.StartHunt(request); |
| 65 | _runner?.Start(jobId); |
| 66 | StartButton.IsEnabled = false; |
| 67 | StopButton.IsEnabled = true; |
| 68 | _metricsTimer?.Start(); |
| 69 | } |
| 70 | |
| 71 | private void OnStop(object sender, RoutedEventArgs e) => _runner?.Cancel(); |
| 72 | |
| 73 | private void OnEvent(JobEvent item) |
| 74 | { |
| 75 | if (item.Type == "progress") |
| 76 | { |
| 77 | ScannedText.Text = item.Scanned.ToString("N0"); |
| 78 | OwnerlessText.Text = item.Matched.ToString("N0"); |
| 79 | return; |
| 80 | } |
| 81 | Append(FeedLine.From(item)); |
| 82 | } |
| 83 | |
| 84 | private void Append(FeedLine line) |
| 85 | { |
| 86 | if (_feed.Count >= MaxFeedLines) |
| 87 | { |
| 88 | _feed.RemoveAt(0); |
| 89 | } |
| 90 | _feed.Add(line); |
| 91 | FeedList.ScrollIntoView(_feed[^1]); |
| 92 | } |
| 93 | } |