using System.Collections.ObjectModel; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using RblxTool.Models; using RblxTool.Services; namespace RblxTool.Views; public sealed partial class GroupsPage : Page { private const int MaxFeedLines = 5000; private readonly ObservableCollection _feed = new(); private JobRunner? _runner; private DispatcherTimer? _metricsTimer; public GroupsPage() { InitializeComponent(); FeedList.ItemsSource = _feed; Loaded += OnLoaded; Unloaded += (_, _) => { _metricsTimer?.Stop(); _runner?.Stop(); }; } private void OnLoaded(object sender, RoutedEventArgs e) { _runner = AppState.Current.CreateRunner(DispatcherQueue); _runner.EventReceived += OnEvent; _runner.Completed += _ => { StartButton.IsEnabled = true; StopButton.IsEnabled = false; _metricsTimer?.Stop(); Append(new FeedLine(" scan finished", FeedTone.Good)); }; _metricsTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(750) }; _metricsTimer.Tick += (_, _) => RequestsText.Text = AppState.Current.Engine.Metrics().Requests.ToString("N0"); } private void OnStart(object sender, RoutedEventArgs e) { if (ClaimToggle.IsOn && AppState.Current.Active is null) { Append(new FeedLine(" claiming needs a signed in account", FeedTone.Bad)); return; } var request = new HuntRequest { Start = (ulong)Math.Max(1, StartBox.Value), End = (ulong)Math.Max(1, EndBox.Value), Threads = (int)Math.Max(1, ThreadsBox.Value), MinMembers = (ulong)Math.Max(0, MinMembersBox.Value), Enrich = EnrichToggle.IsOn, RequirePublicEntry = PublicEntryToggle.IsOn, Claim = ClaimToggle.IsOn, }; _feed.Clear(); Append(new FeedLine($" scanning groups {request.Start}..{request.End}", FeedTone.Accent)); var jobId = AppState.Current.Engine.StartHunt(request); _runner?.Start(jobId); StartButton.IsEnabled = false; StopButton.IsEnabled = true; _metricsTimer?.Start(); } private void OnStop(object sender, RoutedEventArgs e) => _runner?.Cancel(); private void OnEvent(JobEvent item) { if (item.Type == "progress") { ScannedText.Text = item.Scanned.ToString("N0"); OwnerlessText.Text = item.Matched.ToString("N0"); return; } Append(FeedLine.From(item)); } private void Append(FeedLine line) { if (_feed.Count >= MaxFeedLines) { _feed.RemoveAt(0); } _feed.Add(line); FeedList.ScrollIntoView(_feed[^1]); } }