Skip to content

Wizzard to remap missing device for creation#158

Draft
vicocz wants to merge 10 commits into
defaultfrom
local/remap-device-in-action
Draft

Wizzard to remap missing device for creation#158
vicocz wants to merge 10 commits into
defaultfrom
local/remap-device-in-action

Conversation

@vicocz
Copy link
Copy Markdown
Owner

@vicocz vicocz commented Aug 1, 2025

TBD

Resolves #95

@vicocz vicocz changed the title PoC - wizzard to remap missing device Wizzard to remap missing device for creation Aug 12, 2025
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a UI entry point to remap devices used by an imported creation (intended to help when devices are missing) and refactors “Play” command creation into a shared CreationCommandFactory.

Changes:

  • Introduces ICreationCommandFactory and moves Play/remap command logic into CreationCommandFactory.
  • Adds a “Remap device” toolbar command to the Creation page.
  • Adds persistence support for remapping device IDs across controller actions and improves device-id collection (GetDeviceIds returning a set).

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
BrickController2/BrickController2/UI/ViewModels/CreationPageViewModel.cs Switches to ICreationCommandFactory, adds RemapDeviceCommand, removes inline Play logic.
BrickController2/BrickController2/UI/ViewModels/CreationListPageViewModel.cs Switches Play command creation to the command factory.
BrickController2/BrickController2/UI/ViewModels/ControllerProfilePageViewModel.cs Switches Play command creation to the command factory.
BrickController2/BrickController2/UI/Pages/CreationPage.xaml Adds a toolbar item to trigger device remapping.
BrickController2/BrickController2/UI/DI/UiModule.cs Registers CreationCommandFactory as ICreationCommandFactory.
BrickController2/BrickController2/UI/Commands/ICreationCommandFactory.cs New interface extending ICommandFactory<Creation> with Play/remap commands.
BrickController2/BrickController2/UI/Commands/CreationCommandFactory.cs Adds Play/remap command implementations (including remap wizard flow).
BrickController2/BrickController2/CreationManagement/ICreationManager.cs Adds remap API (RemapDevice).
BrickController2/BrickController2/CreationManagement/CreationManager.cs Implements device remap persistence across controller actions.
BrickController2/BrickController2/CreationManagement/Creation.cs Changes GetDeviceIds to return a set and simplifies de-duplication.
BrickController2/BrickController2/CreationManagement/ControllerAction.cs Adds per-action device-id remap helper.
BrickController2/BrickController2/BusinessLogic/PlayLogic.cs Adjusts to GetDeviceIds set semantics; adds GetMissingDevices.
BrickController2/BrickController2/BusinessLogic/IPlayLogic.cs Adds GetMissingDevices to the interface.
Comments suppressed due to low confidence (2)

BrickController2/BrickController2/UI/ViewModels/CreationPageViewModel.cs:64

  • HasMultipleControllerProfiles won’t update when controller profiles are added/removed anymore: the previous RaisePropertyChanged(nameof(HasMultipleControllerProfiles)) calls were removed and there’s no ControllerProfiles.CollectionChanged subscription. This means the Play swipe item visibility can be stale until the page is recreated. Consider raising the property change after add/delete (and import/paste), or subscribe to Creation.ControllerProfiles.CollectionChanged and raise from there (unsubscribe appropriately).
        public Creation Creation { get; }

        public bool HasMultipleControllerProfiles => Creation.ControllerProfiles.Count > 1;

BrickController2/BrickController2/UI/ViewModels/CreationListPageViewModel.cs:52

  • IPlayLogic playLogic is injected and stored in _playLogic, but _playLogic is no longer used in this view model after PlayAsync was removed. Consider removing the unused field/constructor parameter to prevent dead dependencies and warnings.
            ICreationManager creationManager,
            IDeviceManager deviceManager,
            IPlayLogic playLogic,
            IDialogService dialogService,
            ISharedFileStorageService sharedFileStorageService,
            ICreationCommandFactory commandFactory,
            IBluetoothPermission bluetoothPermission,
            IReadWriteExternalStoragePermission readWriteExternalStoragePermission)
            : base(navigationService, translationService)
        {
            _creationManager = creationManager;
            _deviceManager = deviceManager;
            _playLogic = playLogic;
            _dialogService = dialogService;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 21 to +34
private readonly ICreationManager _creationManager;
private readonly IDialogService _dialogService;
private readonly IPlayLogic _playLogic;
private readonly ISharingManager<ControllerProfile> _sharingManagerProfile;

public CreationPageViewModel(
INavigationService navigationService,
ITranslationService translationService,
ICreationManager creationManager,
IDialogService dialogService,
ISharedFileStorageService sharedFileStorageService,
IPlayLogic playLogic,
ISharingManager<ControllerProfile> sharingManagerProfile,
ICommandFactory<Creation> commandFactory,
ICreationCommandFactory commandFactory,
Comment on lines 41 to 45
IPlayLogic playLogic,
IInputDeviceEventService gameControllerService,
ICreationCommandFactory commandFactory,
NavigationParameters parameters)
: base(navigationService, translationService)
Comment on lines +47 to +48
public ICommand PlayControllerProfileCommand(PageViewModelBase viewModel)
=> new SafeCommand<ControllerProfile>((profile) => PlayAsync(viewModel, profile.Creation, profile));
Comment on lines +120 to +137
// get source device IDs
var sourceDeviceIds = creation.GetDeviceIds()
.Select(id =>
{
DeviceId.TryParse(id, out var deviceType, out var deviceAddress);
return (DeviceType: deviceType, Address: deviceAddress);
})
.Where(x => x.DeviceType != DeviceType.Unknown && x.Address != null)
.ToList();

// get source types
var sourceTypes = sourceDeviceIds.Select(x => x.DeviceType).ToHashSet();
var addresses = sourceDeviceIds.Select(x => x.Address!).ToHashSet();
// source types that have some existing device of such type present, but not used in creation
var suitableTypes = sourceTypes.Where(x => _deviceManager.Devices
.Any(d => d.DeviceType == x && !addresses.Contains(d.Address)))
.ToHashSet();

Comment on lines +169 to +171
// choose target device by name but avoid the source one
var suitableDevices = _deviceManager.Devices
.Where(d => d.DeviceType == sourceType.Value && d.Address != sourceDeviceAddress)
<controls:ToolbarIcon Icon="file_upload" Text="{extensions:Translate ExportCreation}" Command="{Binding ExportCreationCommand}" Order="Secondary" />
<controls:ToolbarIcon Icon="copy" Text="{extensions:Translate CopyCreation}" Command="{Binding CopyCreationCommand}" Order="Secondary" />
<controls:ToolbarIcon Icon="paste" Text="{extensions:Translate PasteControllerProfile}" Command="{Binding PasteControllerProfileCommand}" Order="Secondary" />
<controls:ToolbarIcon Icon="find_replace" Text="{extensions:Translate RemapDevice}" Command="{Binding RemapDeviceCommand}" Order="Secondary" />
Task<Creation> AddCreationAsync(string creationName);
Task DeleteCreationAsync(Creation creation);
Task RenameCreationAsync(Creation creation, string newName);
Task<int> RemapDevice(Creation creation, string sourceDeviceId, string newDeviceId);
}
}

public async Task<int> RemapDevice(Creation creation, string sourceDeviceId, string newDeviceId)
Comment on lines +14 to +15
IEnumerable<string> GetMissingDevices(Creation creation);


await DialogService.ShowMessageBoxAsync(
Translate("Information"),
Translate($"Remapped {count} controller actions from device '{sourceDeviceId}' to '{newDeviceId}'"),
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Allow an user to remap of missing devices after import

2 participants