Skip to content

feat: Add Replay Manager tool with cloud sharing and drag-and-drop#233

Closed
undead2146 wants to merge 1 commit intocommunity-outpost:developmentfrom
undead2146:feat/replay-manager
Closed

feat: Add Replay Manager tool with cloud sharing and drag-and-drop#233
undead2146 wants to merge 1 commit intocommunity-outpost:developmentfrom
undead2146:feat/replay-manager

Conversation

@undead2146
Copy link
Copy Markdown
Member

@undead2146 undead2146 commented Jan 1, 2026

This PR introduces a Replay Manager tool to GenHub, enabling users to manage, import, and share Command & Conquer: Generals and Zero Hour replay files directly from the application.

Summary

The Replay Manager is now available as a bundled tool in the Tools tab. It provides a unified interface to handle replay files, supporting drag-and-drop imports, cloud sharing via UploadThing, and local ZIP archiving.

Key Features

  • Unified Replay Management

    • View, sort, and manage replays for both Generals and Zero Hour in a single interface.
    • Support for inline renaming of files directly in the DataGrid.
    • Delete selected replays or reveal them in Windows Explorer.
  • Flexible Importing

    • Drag & Drop: Drop .rep or .zip files directly onto the view to import them.
    • URL Import: Paste URLs from various sources:
      • Direct links (.rep/.zip).
      • Generals Online match pages.
      • GenTool data pages.
      • UploadThing shared links.
    • File Picker: Browse local file system to select replays.
  • Export & Cloud Sharing

    • Local ZIP: Bundle selected replays into a ZIP archive stored in the replay folder.
    • UploadThing Integration: Upload replays to the cloud (UploadThing v7) to generate shareable links.
    • History Tracking: View upload history, verify link validity, and remove old entries.
  • Rate Limiting

    • Enforces a 10MB weekly upload limit to prevent abuse.
    • Tracks usage and calculates reset dates automatically.
  • Validation

    • ZIP archives are validated to ensure they contain only a single layer of .rep files.
    • File size checks (1MB limit per file).

Technical Changes

Core & Infrastructure

  • Added IReplayDirectoryService, IReplayImportService, IReplayExportService, IUploadRateLimitService, IUrlParserService, and IZipValidationService.
  • Implemented new service classes for handling file I/O, HTTP requests, and ZIP operations.
  • Added DotNetEnv package to support loading environment variables (e.g., UPLOADTHING_TOKEN) from a .env file.
  • Added Avalonia.Controls.DataGrid package for the file list view.
  • Registered all new services and the ReplayManagerToolPlugin in the Dependency Injection module.
  • Updated ToolService to distinguish between "bundled" (built-in) and external plugins, preventing the removal of bundled tools.

UI/UX

  • Created ReplayManagerView with a responsive layout, progress bars, and overlay notifications.
  • Implemented ReplayManagerViewModel using the MVVM pattern with CommunityToolkit.Mvvm.
  • Added EnumToBoolConverter and EqualsToConverter for improved data binding.
  • Tools Hub Enhancements: Added a collapsible sidebar feature and updated the "Remove" logic to disable removal for bundled tools. Re-enabled the "Tools" navigation tab.

Documentation

  • Added documentation for the new Tool constants and Replay Manager usage in docs/.

Greptile Summary

  • Introduces a comprehensive Replay Manager tool as a bundled feature in GenHub's Tools tab with drag-and-drop importing, cloud sharing via UploadThing, and local ZIP archiving for Command & Conquer replay files.
  • Implements a new tool plugin architecture distinguishing between built-in bundled tools and external plugins, preventing removal of core functionality like the Replay Manager.
  • Modernizes codebase syntax throughout using C#12collection expressions and proper disposal patterns while adding necessary UI converters and constants for the new functionality.

Important Files Changed

Filename Overview
GenHub/GenHub/Features/Tools/ReplayManager/ViewModels/ReplayManagerViewModel.cs New comprehensive ViewModel with complex async operations, fire-and-forget HTTP tasks that need proper error handling, and potential infinite loop in file naming logic
GenHub/GenHub/Features/Tools/ReplayManager/Views/ReplayManagerView.axaml.cs New code-behind with drag-and-drop functionality but silent error handling and potential null reference issues in drag validation
GenHub/GenHub/Features/Tools/ReplayManager/Services/ReplayExportService.cs New UploadThing cloud integration service with environment variable authentication and proper cleanup, but potential authentication failures if token missing
GenHub/GenHub.Core/Services/Tools/ToolService.cs Updated to support bundled tools architecture with proper DI integration but potential issues if built-in plugins collection is null

Confidence score: 3/5

  • This PR introduces significant new functionality with complex async operations and external service integrations that could fail in production
  • Score lowered due to potential runtime issues in ViewModels (fire-and-forget tasks, file naming conflicts), silent error handling in UI code, and dependency on external environment variables for authentication
  • Pay close attention to ReplayManagerViewModel.cs for async operation handling and ReplayExportService.cs for authentication token management

Sequence Diagram

sequenceDiagram
    participant User
    participant ReplayManagerViewModel
    participant UploadRateLimitService
    participant ReplayExportService
    participant ZipValidationService
    participant HttpClient
    participant UploadThing
    participant Clipboard

    User->>ReplayManagerViewModel: "Click Upload & Share"
    ReplayManagerViewModel->>UploadRateLimitService: "CanUploadAsync(totalSize)"
    UploadRateLimitService-->>ReplayManagerViewModel: "true/false"
    
    alt Upload allowed
        ReplayManagerViewModel->>ReplayExportService: "UploadToUploadThingAsync(replays)"
        
        alt Multiple files or single .rep
            ReplayExportService->>ReplayExportService: "CreateTemporaryZip(replays)"
            ReplayExportService->>ZipValidationService: "ValidateZip(zipPath)"
            ZipValidationService-->>ReplayExportService: "validation result"
        else Single ZIP file
            ReplayExportService->>ZipValidationService: "ValidateZip(existingZip)"
            ZipValidationService-->>ReplayExportService: "validation result"
        end
        
        ReplayExportService->>HttpClient: "POST /prepareUpload"
        HttpClient->>UploadThing: "Request presigned URL"
        UploadThing-->>HttpClient: "Presigned URL + key"
        HttpClient-->>ReplayExportService: "Upload instructions"
        
        ReplayExportService->>HttpClient: "PUT binary data to presigned URL"
        HttpClient->>UploadThing: "Upload file"
        UploadThing-->>HttpClient: "Upload success"
        HttpClient-->>ReplayExportService: "Upload complete"
        
        ReplayExportService-->>ReplayManagerViewModel: "Public URL"
        ReplayManagerViewModel->>Clipboard: "SetTextAsync(url)"
        ReplayManagerViewModel->>UploadRateLimitService: "RecordUpload(size, url, filename)"
        ReplayManagerViewModel->>User: "Show success notification"
    else Upload denied
        ReplayManagerViewModel->>User: "Show rate limit error"
    end
Loading

Context used:

  • Rule from dashboard - What: Enforce Conventional Commits format with allowed types (feat, fix, docs, style, refactor, perf... (source)
  • Context from dashboard - Coding style used in the application which PullRequests and coding style has to be applied to. (source)

…le management

- Implemented ReplayManagerView for managing replay files.
- Added drag-and-drop support for importing replay files (.rep, .zip).
- Enhanced ToolsViewModel to include Replay Manager services.
- Updated UI styles for better visual consistency.
- Introduced EnumToBoolConverter and EqualsToConverter for improved data binding.
- Added documentation for Replay Manager features and usage.
- Registered Replay Manager services in the dependency injection module.
@undead2146 undead2146 added Enhancement New feature or request GUI For graphical user interface labels Jan 1, 2026
@undead2146 undead2146 force-pushed the development branch 3 times, most recently from b9f8255 to 615dc70 Compare January 3, 2026 13:22
@undead2146
Copy link
Copy Markdown
Member Author

@greptile

Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (14)

  1. GenHub/GenHub.Core/Models/Tools/ToolMetadata.cs, line 21-26 (link)

    syntax: The XML documentation comments for Version (line 21-22) and Author (line 24-26) properties are swapped. Version property has description 'Gets or sets the author of the tool' and Author property has description 'Gets or sets the version of the tool'.

  2. GenHub/GenHub.Core/Interfaces/Tools/ReplayManager/IUrlParserService.cs, line 32 (link)

    style: method returns nullable string but doesn't document when null is returned

    Should the XML documentation specify under what conditions null is returned (e.g., invalid URL, network error, unsupported source)?

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

  3. GenHub/GenHub/Infrastructure/Converters/EnumToBoolConverter.cs, line 21 (link)

    style: String comparison for enum values may not handle all edge cases correctly. Consider using Equals() method or direct enum comparison for better type safety. Are there specific enum types this converter needs to handle that might have custom ToString() implementations?

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

  4. GenHub/GenHub.Core/Interfaces/Tools/ReplayManager/UsageInfo.cs, line 12 (link)

    style: missing newline at end of file

  5. GenHub/GenHub/Features/Tools/ReplayManager/ReplayManagerToolPlugin.cs, line 2 (link)

    style: System.Collections.Generic import is unused

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

  6. GenHub/GenHub.Core/Constants/PlatformConstants.cs, line 16 (link)

    style: The select argument format string includes "{0}" but should be properly documented to indicate what parameter is expected (file path).

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

  7. GenHub/GenHub.Core/Interfaces/Tools/ReplayManager/IUploadRateLimitService.cs, line 29 (link)

    style: RecordUpload is synchronous while other methods are async - consider making this async for consistency. Is there a specific reason this method needs to be synchronous while others are async?

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

  8. GenHub/GenHub/Features/Tools/ReplayManager/ViewModels/ReplayManagerViewModel.cs, line 467-478 (link)

    logic: Potential infinite loop if directory lacks write permissions - the while loop will continue indefinitely as File.Exists will keep returning true for the same path.

  9. GenHub/GenHub/Features/Tools/ReplayManager/Services/ReplayExportService.cs, line 91-95 (link)

    style: File.Delete in finally block could throw if file is locked or inaccessible, potentially masking original exceptions from the try block

  10. GenHub/GenHub/Features/Tools/ReplayManager/Services/ReplayExportService.cs, line 185 (link)

    logic: FileStream is not disposed properly - it's passed to StreamContent but may not be disposed when MultipartFormDataContent is disposed

  11. GenHub/GenHub/Features/Tools/ReplayManager/ViewModels/UploadHistoryItemViewModel.cs, line 58 (link)

    style: Consider using constants from UiConstants for status colors instead of hardcoded hex values

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

    Context Used: Context from dashboard - Coding style used in the application which PullRequests and coding style has to be applied to. (source)

  12. GenHub/GenHub/Features/Tools/ReplayManager/Services/UploadRateLimitService.cs, line 227 (link)

    logic: returning empty list when file is corrupt could lead to data loss since the cache becomes empty and subsequent saves would overwrite the corrupted file. Should the service attempt to backup the corrupted file before returning an empty list, or throw an exception to prevent potential data loss?

  13. GenHub/GenHub.Core/Services/Tools/ToolService.cs, line 207 (link)

    logic: Empty catch block discards all exception information. At minimum, the exception should be logged for debugging purposes.

  14. GenHub/GenHub/Features/Tools/ReplayManager/Views/ReplayManagerView.axaml.cs, line 58-61 (link)

    style: Automatically adding .rep extension modifies user input without their consent and could cause issues if they intentionally omitted it. Should this behavior be optional or provide user confirmation before modifying the filename?

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

60 files reviewed, 14 comments

Edit Code Review Agent Settings | Greptile

@undead2146
Copy link
Copy Markdown
Member Author

Closed as of #238

@undead2146 undead2146 closed this Jan 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement New feature or request GUI For graphical user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant