upgrade to .NET, fix webOS 26 compatibility, run new UI in separate process

This commit is contained in:
Maassoft committed 2026-05-02 17:39:33 +02:00
1 parent 8cb427f0b0
commit d0d3bb4682
80 files changed
+1517 -912

No files matched your search

+22 -4
View File
@@ -1,5 +1,6 @@
@using ColorControl.Shared.Common
@using ColorControl.Shared.Contracts
@using ColorControl.UI.Pages.Generic
@using ColorControl.UI.Services
@using ColorControl.UI.Components.Pages.Generic
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@@ -9,6 +10,7 @@
@inject NavigationManager _navigationManager
@inject NotificationService _notificationService
@inject ProtectedSessionStorage _sessionStorage
@inject JSHelper _jsHelper
@implements IDisposable
@attribute [StreamRendering]
@@ -20,19 +22,26 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<ResourcePreloader />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="ColorControl.UI.styles.css" />
<ImportMap />
<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet />
<HeadOutlet @rendermode="InteractiveServer" />
<script>
addEventListener('focus', (event) => {
var isModalShown = document.getElementsByClassName("modal show").length > 0;
DotNet.invokeMethodAsync("ColorControl.UI", "RefreshSummary", isModalShown);
});
</script>
</head>
<body>
<Routes />
<script src="_framework/blazor.web.js"></script>
<Routes @rendermode="InteractiveServer" />
<script src="@Assets["_framework/blazor.web.js"]"></script>
<NotificationsComponent></NotificationsComponent>
</body>
@@ -59,4 +68,13 @@
{
AppState.OnChange -= StateHasChanged;
}
[JSInvokable]
public static async Task RefreshSummary(bool isModalShown)
{
if (Blazor.CurrentComponent is SummaryComponentBase summaryComponent && !isModalShown)
{
await summaryComponent.RefreshExternal();
}
}
}
@@ -3,10 +3,12 @@
@using ColorControl.Shared.Common
@using ColorControl.Shared.Contracts
@using ColorControl.Shared.Contracts.AMD
@using ColorControl.UI.Pages.Generic
@using ColorControl.UI.Services;
@using ColorControl.UI.Components.Pages.Generic
@using ColorControl.UI.Generics
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inherits SummaryComponentBase
@rendermode Constants.RenderMode
@@ -144,6 +146,13 @@ else
private PresetOrder PresetOrder;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
await Refresh();
}
protected override async Task Refresh()
{
await RefreshPresets();
DisplayPresets = await _rpcClientService.CallAsync<List<AmdPreset>>("AmdService", "GetDisplayPresets");
@@ -5,7 +5,9 @@
@using ColorControl.Shared.Contracts.DisplayInfo
@using ColorControl.UI.Components.Pages.Generic
@using ColorControl.UI.Generics
@using ColorControl.UI.Pages.Generic
@using ColorControl.UI.Services
@inherits SummaryComponentBase
@rendermode Constants.RenderMode
@@ -190,7 +192,15 @@ else
private FieldDefinition AskHdrAssociationField = new FieldDefinition { Label = "Associate as HDR profile", FieldType = FieldType.CheckBox, Value = false };
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
await Refresh();
}
protected override async Task Refresh()
{
await RefreshDisplays();
}
@@ -3,7 +3,6 @@
@using ColorControl.Shared.Contracts.Game
@using ColorControl.UI.Services
@using ColorControl.UI.Components.Pages.Generic
@using NvAPIWrapper.Native.Display
@using ColorControl.Shared.Common
@rendermode Constants.RenderMode
@@ -0,0 +1,20 @@
using Microsoft.AspNetCore.Components;
namespace ColorControl.UI.Pages.Generic;
public abstract class CustomComponentBase : ComponentBase, IDisposable
{
public void Dispose()
{
GC.SuppressFinalize(this);
Blazor.ClearCurrentComponent(this);
}
protected override Task OnInitializedAsync()
{
Blazor.SetCurrentComponent(this);
return Task.CompletedTask;
}
}
@@ -44,9 +44,9 @@
try
{
var options = new RpcUiClientOptions
{
Timeout = 60000
};
{
Timeout = 60000
};
var result = await _rpcClientService.CallWithOptionsAsync<string>("GameService", "SelectPath", options);
@@ -0,0 +1,13 @@
namespace ColorControl.UI.Pages.Generic;
public abstract class SummaryComponentBase : CustomComponentBase
{
protected abstract Task Refresh();
public async Task RefreshExternal()
{
await Refresh();
await InvokeAsync(StateHasChanged);
}
}
@@ -7,16 +7,20 @@
@if (Triggers != null)
{
if (!Triggers.Any())
if (Triggers.Count < 2)
{
<div>
<label class="form-label">No triggers found. Click to add:</label>
<label class="form-label">Add trigger:</label>
<button class="btn btn-primary btn-sm" type="button" @onclick="() => Triggers.Add(new PresetTrigger())">Add</button>
</div>
}
foreach (var trigger in Triggers)
{
<div class="clearfix">
<label class="form-label">Trigger @(Triggers.IndexOf(trigger) + 1)</label>
<button class="btn btn-danger btn-sm float-end" type="button" @onclick="() => Triggers.Remove(trigger)">Remove</button>
</div>
<div class="mb-2">
<label class="form-label" for="triggerType">Trigger type</label>
<select class="form-select" id="triggerType" @bind="trigger.Trigger">
@@ -26,7 +30,7 @@
}
</select>
</div>
<FlagsInput Label="Conditions" Value="@((uint)trigger.Conditions)" Labels="ConditionLabels" Col="6" ValueChanged="ConditionsChanged"></FlagsInput>
<FlagsInput Label="Conditions" Value="@((uint)trigger.Conditions)" Labels="ConditionLabels" Col="6" ValueChanged="value => ConditionsChanged(value, trigger)"></FlagsInput>
<div class="mb-2">
<label class="form-label" for="includedProcesses">Included processes</label>
<input class="form-control" type="text" @bind="trigger.IncludedProcessesAsString" />
@@ -40,6 +44,11 @@
<input class="form-control" type="text" @bind="trigger.ConnectedDisplaysRegex"
title="The preset will be executed only if the supplied Regular Expression matches the device name of at least one of the displays that are connected at the moment the trigger is fired." />
</div>
@if (Triggers.IndexOf(trigger) < Triggers.Count - 1)
{
<div class="border-bottom mb-2"></div>
}
}
}
@@ -49,14 +58,8 @@
private List<string> ConditionLabels = Utils.GetDescriptions<PresetConditionType>(fromValue: 1).ToList();
public void ConditionsChanged(uint value)
public void ConditionsChanged(uint value, PresetTrigger trigger)
{
if (Triggers == null || !Triggers.Any())
{
return;
}
var trigger = Triggers.First();
trigger.Conditions = (PresetConditionType)value;
}
}
@@ -1,7 +1,7 @@
@using ColorControl.Shared.Contracts
@using ColorControl.Shared.Contracts.LG
@using ColorControl.UI.Services
@using NvAPIWrapper.Native.Display
@using Microsoft.AspNetCore.Components.Web
@using ColorControl.Shared.Common
@using ColorControl.UI.Components.Pages.Generic
@@ -154,6 +154,10 @@
<input class="form-check-input" type="checkbox" role="switch" id="checkUseSecureConnection" @bind="Device.Options.UseSecureConnection">
<label class="form-check-label" for="checkUseSecureConnection">Use secure connection</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="checkUseNewHandshake" @bind="Device.Options.UseNewHandshake">
<label class="form-check-label" for="checkUseNewHandshake">Enable webOS 26 compatibility</label>
</div>
</div>
</div>
</div>
@@ -2,7 +2,6 @@
@using ColorControl.Shared.Contracts.LG
@using ColorControl.UI.Services
@using ColorControl.UI.Components.Pages.Generic
@using NvAPIWrapper.Native.Display
@using ColorControl.Shared.Common
@using static ColorControl.UI.Components.Pages.Generic.StepsInput<ColorControl.Shared.Contracts.LG.LgPreset>
@@ -5,10 +5,12 @@
@using ColorControl.Shared.Contracts.NVIDIA
@using ColorControl.Shared.Contracts.LG
@using ColorControl.UI.Components.Pages.RemoteControl
@using ColorControl.UI.Pages.Generic
@using ColorControl.UI.Services;
@using ColorControl.UI.Components.Pages.Generic
@using ColorControl.UI.Generics
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inherits SummaryComponentBase
@rendermode Constants.RenderMode
@@ -239,6 +241,13 @@ else
private List<LgPreset> RcPresets = [LgPresets.InStartPreset, LgPresets.EzAdjustPreset];
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
await Refresh();
}
protected override async Task Refresh()
{
Config = await _rpcClientService.CallAsync<LgServiceConfigDto>("LgService", "GetConfig");
await RefreshPresets();
@@ -1,7 +1,6 @@
@using ColorControl.Shared.Contracts
@using ColorControl.Shared.Contracts.NVIDIA
@using ColorControl.UI.Services;
@using NvAPIWrapper.Native.Display
@using ColorControl.Shared.Common;
@rendermode Constants.RenderMode
@@ -2,7 +2,6 @@
@using ColorControl.Shared.Contracts.NVIDIA
@using ColorControl.UI.Components.Pages.Generic
@using ColorControl.UI.Services;
@using NvAPIWrapper.Native.Display
@using ColorControl.Shared.Common;
@rendermode Constants.RenderMode
@@ -2,7 +2,6 @@
@using ColorControl.Shared.Contracts.NVIDIA
@using ColorControl.UI.Components.Pages.Generic
@using ColorControl.UI.Services;
@using NvAPIWrapper.Native.Display
@using ColorControl.Shared.Common;
@rendermode Constants.RenderMode
@@ -1,7 +1,6 @@
@using ColorControl.Shared.Contracts
@using ColorControl.Shared.Contracts.NVIDIA
@using ColorControl.UI.Services;
@using NvAPIWrapper.Native.Display
@using ColorControl.Shared.Common;
@using static ColorControl.Shared.Common.NestedItemsBuilder
@@ -45,50 +45,62 @@
}
<div class="accordion accordion-flush" id="presetAccordion">
@if (!Preset.IsDisplayPreset)
{
<div class="accordion-item">
<h2 class="accordion-header">
<span class="d-flex align-items-baseline">
@if (!Preset.IsDisplayPreset)
{
<input class="form-check-input me-1" style="font-size: 1rem; visibility: hidden" type="checkbox">
}
<button class="accordion-button collapsed py-2" type="button" data-bs-toggle="collapse" data-bs-target="#displaySettings">
Display
</button>
</span>
</h2>
<div id="displaySettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
<div class="accordion-body">
<div class="accordion-item">
<h2 class="accordion-header">
<span class="d-flex align-items-baseline">
@if (!Preset.IsDisplayPreset)
{
<input class="form-check-input me-1" style="font-size: 1rem; visibility: hidden" type="checkbox">
}
<button class="accordion-button collapsed py-2" type="button" data-bs-toggle="collapse" data-bs-target="#displaySettings">
Display
</button>
</span>
</h2>
<div id="displaySettings" class="accordion-collapse collapse" data-bs-parent="#presetAccordion">
<div class="accordion-body">
@if (!Preset.IsDisplayPreset)
{
<div class="mb-2">
<input class="form-check-input" type="checkbox" @bind="Preset.primaryDisplay" id="primaryDisplay">
<label class="form-check-label" for="primaryDisplay">
Primary display
</label>
</div>
@if (displayPresets != null)
}
@if (displayPresets != null)
{
if (!Preset.IsDisplayPreset)
{
<div class="mb-2">
<label class="form-label" for="mode">Display</label>
<select class="form-select" id="mode" @bind="Preset.DisplayId" disabled="@(Preset.primaryDisplay)">
<select class="form-select" id="mode" @bind="Preset.DisplayId" disabled="@Preset.primaryDisplay">
@foreach (var display in displayPresets)
{
<option value="@display.DisplayId">@display.displayName</option>
}
</select>
</div>
<div class="mb-2">
<input class="form-check-input" type="checkbox" @bind="Preset.DisplayConfig.IsPrimary" id="setAsPrimaryDisplay" disabled="@(Preset.primaryDisplay)">
<label class="form-check-label" for="setAsPrimaryDisplay">
Set display as primary display
</label>
</div>
}
<div class="mb-2">
<input class="form-check-input" type="checkbox" @bind="Preset.DisplayConfig.IsPrimary" id="setAsPrimaryDisplay" disabled="@(Preset.IsDisplayPreset && displayPresets.Count == 1)">
<label class="form-check-label" for="setAsPrimaryDisplay">
Set display as primary display
</label>
</div>
}
<div class="mb-2">
<label class="form-label" for="connectivity">Connectivity</label>
<select class="form-select" id="scaling" @bind="Preset.DisplayConfig.Connectivity">
@foreach (var connectivity in Enum.GetValues<Shared.Contracts.DisplayConnectivity>())
{
<option value="@connectivity.ToString()">@connectivity.ToString()</option>
}
</select>
</div>
</div>
</div>
}
</div>
@if (resolutions != null)
{
@@ -745,7 +757,7 @@
ApplyImmediately = false;
Preset = PresetParam == null ? null : PresetParam.CloneWithId();
Preset = PresetParam?.CloneWithId();
displayPresets = await _rpcClientService.CallAsync<List<NvPreset>>("NvService", "GetDisplayPresets");
if (Preset?.IsDisplayPreset == true)
@@ -2,11 +2,13 @@
@using ColorControl.Shared.Contracts
@using ColorControl.Shared.Contracts.NVIDIA
@using ColorControl.UI.Pages.Generic
@using ColorControl.UI.Services;
@using ColorControl.UI.Components.Pages.Generic
@using ColorControl.Shared.Common;
@using ColorControl.UI.Generics
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inherits SummaryComponentBase
@rendermode Constants.RenderMode
@@ -276,6 +278,13 @@ else
private PresetOrder PresetOrder;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
await Refresh();
}
protected override async Task Refresh()
{
NvConfig = await _rpcClientService.CallAsync<NvServiceConfig>("NvService", "GetConfig");
await RefreshPresets();
@@ -2,7 +2,6 @@
@using ColorControl.Shared.Contracts.Base
@using ColorControl.Shared.Contracts.RemoteControl
@using ColorControl.UI.Services
@using NvAPIWrapper.Native.Display
@using ColorControl.Shared.Common
@using System.Globalization
@@ -2,7 +2,6 @@
@using ColorControl.Shared.Contracts.Samsung
@using ColorControl.UI.Components.Pages.Generic
@using ColorControl.UI.Services
@using NvAPIWrapper.Native.Display
@using ColorControl.Shared.Common
@rendermode Constants.RenderMode
@@ -2,7 +2,6 @@
@using ColorControl.Shared.Contracts.Samsung
@using ColorControl.UI.Services
@using ColorControl.UI.Components.Pages.Generic
@using NvAPIWrapper.Native.Display
@using ColorControl.Shared.Common
@using static ColorControl.UI.Components.Pages.Generic.StepsInput<ColorControl.Shared.Contracts.Samsung.SamsungPreset>
@@ -102,8 +102,8 @@
SecondaryAction = FactoryMenuSecondStepEnterWithoutExecute;
Fields =
[
AddField("Service Menu - Advanced", null, FieldType.Label, "If the service menu opened and you want to access the Advanced settings, click 'Next >' or click 'Skip' to skip"),
AddField("Advanced Unlock Type", AdvancedUnlockType.TV, subLabel: "Select the desired unlock type for the Advanced section. If the target is a TV choose TV, otherwise choose Monitor")
AddField("Service Menu - Advanced", null, FieldType.Label, "If the service menu opened and you want to access the Advanced settings, click 'Next >' or click 'Skip' to skip. You can also manually enter the unlock codes 0098 (for TV's) and 0038 (for monitors) while the 'Advanced' item is highlighted."),
AddField("Advanced Unlock Type", AdvancedUnlockType.TV, subLabel: "Select the desired unlock type for the Advanced section. If the target is a TV choose TV, otherwise choose Monitor")
];
StateHasChanged();
@@ -5,10 +5,12 @@
@using ColorControl.Shared.Contracts.NVIDIA
@using ColorControl.Shared.Contracts.Samsung
@using ColorControl.UI.Components.Pages.RemoteControl
@using ColorControl.UI.Pages.Generic
@using ColorControl.UI.Services;
@using ColorControl.UI.Components.Pages.Generic
@using ColorControl.UI.Generics
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inherits SummaryComponentBase
@rendermode Constants.RenderMode
@@ -220,6 +222,13 @@ else
private PresetOrder PresetOrder;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
await Refresh();
}
protected override async Task Refresh()
{
Config = await _rpcClientService.CallAsync<SamsungServiceConfigDto>("SamsungService", "GetConfig");
await RefreshPresets();