Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f28d26b585
|
||
|
|
a7413c4b0e
|
||
|
|
ead3315170
|
||
|
|
0a0ce5c267
|
||
|
|
01f3544f78
|
||
|
|
8d806d5bff
|
||
|
|
3a268dcaf1
|
||
|
|
2de313c966
|
||
|
|
198ba358dd
|
||
|
|
5a36cd9b21
|
||
|
|
de22472482
|
||
|
|
14f989f35a
|
||
|
|
188187bf83
|
No files matched your search
@@ -6,7 +6,8 @@
|
|||||||
"version": "0.0.1298",
|
"version": "0.0.1298",
|
||||||
"commands": [
|
"commands": [
|
||||||
"vpk"
|
"vpk"
|
||||||
]
|
],
|
||||||
|
"rollForward": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+57
-104
@@ -1,5 +1,4 @@
|
|||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
@@ -9,90 +8,47 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
workflow_dispatch:
|
concurrency:
|
||||||
|
group: ${{ gitea.workflow }}-${{ gitea.ref }}
|
||||||
|
cancel-in-progress: ${{ !startsWith(gitea.ref, 'refs/tags/') }}
|
||||||
|
env:
|
||||||
|
NUGET_PACKAGES: ${{ runner.temp }}\.nuget\packages
|
||||||
|
DOTNET_NOLOGO: true
|
||||||
|
DOTNET_CLI_TELEMETRY_OPT_OUT: true
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build-and-test:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
env:
|
timeout-minutes: 20
|
||||||
NUGET_PACKAGES: ${{ runner.temp }}/.nuget/packages
|
|
||||||
DOTNET_NOLOGO: true
|
|
||||||
DOTNET_CLI_TELEMETRY_OPT_OUT: true
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
|
||||||
with:
|
with:
|
||||||
fetch-depth: 1
|
fetch-depth: 1
|
||||||
|
|
||||||
- name: Setup .NET 8 SDK
|
- name: Setup .NET 8 SDK
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9
|
||||||
with:
|
with:
|
||||||
dotnet-version: 8.0.424
|
dotnet-version: 8.0.x
|
||||||
env:
|
|
||||||
DOTNET_INSTALL_DIR: ${{ runner.temp }}\dotnet
|
|
||||||
|
|
||||||
- name: Cache NuGet packages
|
- name: Cache NuGet packages
|
||||||
id: nuget-cache
|
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
|
||||||
uses: actions/cache@v4
|
|
||||||
continue-on-error: true
|
|
||||||
with:
|
with:
|
||||||
path: ${{ runner.temp }}/.nuget/packages
|
path: ${{ runner.temp }}\.nuget\packages
|
||||||
key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj', '.config/dotnet-tools.json') }}
|
key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj', 'global.json', '.config/dotnet-tools.json') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
nuget-${{ runner.os }}-
|
nuget-${{ runner.os }}-
|
||||||
|
|
||||||
- name: Cache status
|
|
||||||
if: always()
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
Write-Host "NuGet cache hit: ${{ steps.nuget-cache.outputs.cache-hit }}"
|
|
||||||
|
|
||||||
- name: Restore tools
|
- name: Restore tools
|
||||||
run: dotnet tool restore
|
shell: powershell
|
||||||
|
|
||||||
- name: Restore
|
|
||||||
run: dotnet restore src/RgbLedStripController/RgbLedStripController.csproj --configfile NuGet.Config
|
|
||||||
|
|
||||||
- name: Build (Release)
|
|
||||||
run: dotnet build src/RgbLedStripController/RgbLedStripController.csproj -c Release --no-restore
|
|
||||||
|
|
||||||
test:
|
|
||||||
runs-on: windows-latest
|
|
||||||
env:
|
|
||||||
NUGET_PACKAGES: ${{ runner.temp }}/.nuget/packages
|
|
||||||
DOTNET_NOLOGO: true
|
|
||||||
DOTNET_CLI_TELEMETRY_OPT_OUT: true
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 1
|
|
||||||
|
|
||||||
- name: Setup .NET 8 SDK
|
|
||||||
uses: actions/setup-dotnet@v4
|
|
||||||
with:
|
|
||||||
dotnet-version: 8.0.424
|
|
||||||
env:
|
|
||||||
DOTNET_INSTALL_DIR: ${{ runner.temp }}\dotnet
|
|
||||||
|
|
||||||
- name: Cache NuGet packages
|
|
||||||
id: nuget-cache
|
|
||||||
uses: actions/cache@v4
|
|
||||||
continue-on-error: true
|
|
||||||
with:
|
|
||||||
path: ${{ runner.temp }}/.nuget/packages
|
|
||||||
key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj', '.config/dotnet-tools.json') }}
|
|
||||||
restore-keys: |
|
|
||||||
nuget-${{ runner.os }}-
|
|
||||||
|
|
||||||
- name: Cache status
|
|
||||||
if: always()
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
run: |
|
||||||
Write-Host "NuGet cache hit: ${{ steps.nuget-cache.outputs.cache-hit }}"
|
$ErrorActionPreference = "Stop"
|
||||||
|
dotnet tool restore --tool-manifest .config/dotnet-tools.json
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw "tool restore failed ($LASTEXITCODE)" }
|
||||||
|
- name: Restore
|
||||||
|
shell: powershell
|
||||||
|
run: dotnet restore src/RgbLedStripController/RgbLedStripController.csproj --configfile NuGet.Config
|
||||||
|
- name: Build (Release)
|
||||||
|
shell: powershell
|
||||||
|
run: dotnet build src/RgbLedStripController/RgbLedStripController.csproj -c Release --no-restore
|
||||||
- name: Run tests (if any test projects exist)
|
- name: Run tests (if any test projects exist)
|
||||||
shell: pwsh
|
shell: powershell
|
||||||
run: |
|
run: |
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
$tests = @(Get-ChildItem -Recurse -Filter "*Tests.csproj" | Where-Object { $_.FullName -notlike "*\obj\*" -and $_.FullName -notlike "*\bin\*" })
|
$tests = @(Get-ChildItem -Recurse -Filter "*Tests.csproj" | Where-Object { $_.FullName -notlike "*\obj\*" -and $_.FullName -notlike "*\bin\*" })
|
||||||
@@ -104,57 +60,54 @@ jobs:
|
|||||||
dotnet test $t.FullName -c Release
|
dotnet test $t.FullName -c Release
|
||||||
if ($LASTEXITCODE -ne 0) { throw "dotnet test failed for $($t.FullName)" }
|
if ($LASTEXITCODE -ne 0) { throw "dotnet test failed for $($t.FullName)" }
|
||||||
}
|
}
|
||||||
|
|
||||||
release:
|
release:
|
||||||
needs:
|
needs:
|
||||||
- build
|
- build-and-test
|
||||||
- test
|
if: startsWith(gitea.ref, 'refs/tags/v')
|
||||||
if: startsWith(gitea.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
|
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
env:
|
timeout-minutes: 30
|
||||||
NUGET_PACKAGES: ${{ runner.temp }}/.nuget/packages
|
|
||||||
DOTNET_NOLOGO: true
|
|
||||||
DOTNET_CLI_TELEMETRY_OPT_OUT: true
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
|
||||||
with:
|
with:
|
||||||
fetch-depth: 1
|
fetch-depth: 1
|
||||||
|
|
||||||
- name: Setup .NET 8 SDK
|
- name: Setup .NET 8 SDK
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9
|
||||||
with:
|
with:
|
||||||
dotnet-version: 8.0.424
|
dotnet-version: 8.0.x
|
||||||
env:
|
|
||||||
DOTNET_INSTALL_DIR: ${{ runner.temp }}\dotnet
|
|
||||||
|
|
||||||
- name: Cache NuGet packages
|
- name: Cache NuGet packages
|
||||||
id: nuget-cache
|
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
|
||||||
uses: actions/cache@v4
|
|
||||||
continue-on-error: true
|
|
||||||
with:
|
with:
|
||||||
path: ${{ runner.temp }}/.nuget/packages
|
path: ${{ runner.temp }}\.nuget\packages
|
||||||
key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj', '.config/dotnet-tools.json') }}
|
key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj', 'global.json', '.config/dotnet-tools.json') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
nuget-${{ runner.os }}-
|
nuget-${{ runner.os }}-
|
||||||
|
|
||||||
- name: Cache status
|
|
||||||
if: always()
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
Write-Host "NuGet cache hit: ${{ steps.nuget-cache.outputs.cache-hit }}"
|
|
||||||
|
|
||||||
- name: Restore tools
|
- name: Restore tools
|
||||||
run: dotnet tool restore
|
shell: powershell
|
||||||
|
|
||||||
- name: Package with Velopack (Setup.exe + Portable.zip)
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
run: |
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
& powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts/release/package-velopack.ps1
|
dotnet tool restore --tool-manifest .config/dotnet-tools.json
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw "tool restore failed ($LASTEXITCODE)" }
|
||||||
|
- name: Assert tag matches csproj version
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
$ref = "${{ gitea.ref_name }}"
|
||||||
|
$projXml = [xml](Get-Content src/RgbLedStripController/RgbLedStripController.csproj)
|
||||||
|
$version = $projXml.Project.PropertyGroup | Where-Object { $_.Version } | Select-Object -First 1 -ExpandProperty Version
|
||||||
|
if ("v$version" -ne $ref) { throw "Tag $ref does not match csproj version $version" }
|
||||||
|
- name: Package with Velopack (Setup.exe + Portable.zip)
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
& "$env:GITHUB_WORKSPACE/scripts/release/package-velopack.ps1"
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw "package-velopack.ps1 failed ($LASTEXITCODE)" }
|
||||||
|
$out = Join-Path $env:GITHUB_WORKSPACE "artifacts/velopack/win-x64-stable"
|
||||||
|
foreach ($p in @("*.exe", "*.zip", "*.json", "*.nupkg")) {
|
||||||
|
if (@(Get-ChildItem -Path (Join-Path $out $p) -File -ErrorAction SilentlyContinue).Count -eq 0) { throw "Velopack output missing pattern $p in $out" }
|
||||||
|
}
|
||||||
- name: Create Gitea Release with assets
|
- name: Create Gitea Release with assets
|
||||||
uses: akkuman/gitea-release-action@v1
|
uses: akkuman/gitea-release-action@5a83c90484ef4355121df5eb60558c8ce66e81ac
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.API_TOKEN }}
|
token: ${{ secrets.API_TOKEN }}
|
||||||
tag_name: ${{ gitea.ref_name }}
|
tag_name: ${{ gitea.ref_name }}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"sdk": {
|
||||||
|
"version": "8.0.100",
|
||||||
|
"rollForward": "latestFeature"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
5. Çıktı: artifacts/velopack/win-x64-stable/
|
5. Çıktı: artifacts/velopack/win-x64-stable/
|
||||||
|
|
||||||
.NOTES
|
.NOTES
|
||||||
Velopack CLI: dotnet tool restore ile yüklenen vpk kullanılır
|
Velopack CLI: NuGet paketinden dogrudan calistirilan vpk.dll kullanilir
|
||||||
Icon: Assets/AppIcon.ico (installer ikonu)
|
Icon: Assets/AppIcon.ico (installer ikonu)
|
||||||
Velopack CLI args: camelCase (--outputDir, --packId, --packTitle, --packAuthors, --packVersion, --packDir, --mainExe)
|
Velopack CLI args: camelCase (--outputDir, --packId, --packTitle, --packAuthors, --packVersion, --packDir, --mainExe)
|
||||||
#>
|
#>
|
||||||
@@ -66,11 +66,16 @@ $publishArgs = @(
|
|||||||
Write-Host "dotnet publish..." -ForegroundColor Cyan
|
Write-Host "dotnet publish..." -ForegroundColor Cyan
|
||||||
if (-not $WhatIf) {
|
if (-not $WhatIf) {
|
||||||
& dotnet $publishArgs
|
& dotnet $publishArgs
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw "dotnet publish failed ($LASTEXITCODE)" }
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[WhatIf] dotnet $publishArgs"
|
Write-Host "[WhatIf] dotnet $publishArgs"
|
||||||
}
|
}
|
||||||
|
|
||||||
# 2. vpk pack (args camelCase)
|
# 2. vpk pack (args camelCase)
|
||||||
|
$nugetPkgs = $env:NUGET_PACKAGES
|
||||||
|
if (-not $nugetPkgs) { $nugetPkgs = Join-Path $env:USERPROFILE ".nuget/packages" }
|
||||||
|
$vpkDll = Join-Path $nugetPkgs "vpk/0.0.1298/tools/net8.0/any/vpk.dll"
|
||||||
|
if (-not (Test-Path $vpkDll)) { throw "vpk.dll not found at $vpkDll" }
|
||||||
$vpkArgs = @(
|
$vpkArgs = @(
|
||||||
"pack",
|
"pack",
|
||||||
"--outputDir", $velopackDir,
|
"--outputDir", $velopackDir,
|
||||||
@@ -84,9 +89,10 @@ $vpkArgs = @(
|
|||||||
)
|
)
|
||||||
Write-Host "vpk pack..." -ForegroundColor Cyan
|
Write-Host "vpk pack..." -ForegroundColor Cyan
|
||||||
if (-not $WhatIf) {
|
if (-not $WhatIf) {
|
||||||
& dotnet tool run vpk $vpkArgs
|
& dotnet $vpkDll $vpkArgs
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw "vpk pack failed ($LASTEXITCODE)" }
|
||||||
} else {
|
} else {
|
||||||
Write-Host "[WhatIf] dotnet tool run vpk $vpkArgs"
|
Write-Host "[WhatIf] dotnet $vpkDll $vpkArgs"
|
||||||
}
|
}
|
||||||
|
|
||||||
# 3. Sadece Setup.exe ve Portable.zip'i istenen formata rename et
|
# 3. Sadece Setup.exe ve Portable.zip'i istenen formata rename et
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<Version>0.3.0</Version>
|
<Version>0.3.2</Version>
|
||||||
<AssemblyVersion>0.3.0.0</AssemblyVersion>
|
<AssemblyVersion>0.3.2.0</AssemblyVersion>
|
||||||
<FileVersion>0.3.0.0</FileVersion>
|
<FileVersion>0.3.2.0</FileVersion>
|
||||||
<InformationalVersion>0.3.0</InformationalVersion>
|
<InformationalVersion>0.3.2</InformationalVersion>
|
||||||
<AssemblyProduct>Fristy.RgbLedStripController</AssemblyProduct>
|
<AssemblyProduct>Fristy.RgbLedStripController</AssemblyProduct>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ public sealed class BleDeviceService : IBleTransport
|
|||||||
await MergeWindowsDeviceInventoryAsync(captures);
|
await MergeWindowsDeviceInventoryAsync(captures);
|
||||||
|
|
||||||
return captures.Values
|
return captures.Values
|
||||||
|
.Where(capture => IsSupportedAddress(capture.Address))
|
||||||
.Select(capture => new BleScanResult
|
.Select(capture => new BleScanResult
|
||||||
{
|
{
|
||||||
DeviceId = FormatAddress(capture.Address),
|
DeviceId = FormatAddress(capture.Address),
|
||||||
@@ -299,6 +300,9 @@ public sealed class BleDeviceService : IBleTransport
|
|||||||
|| normalized.Contains("DUOCO");
|
|| normalized.Contains("DUOCO");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static bool IsSupportedAddress(ulong address)
|
||||||
|
=> FormatAddress(address).StartsWith("BE:", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
private static async Task RunScanPassAsync(
|
private static async Task RunScanPassAsync(
|
||||||
ConcurrentDictionary<ulong, ScanCapture> captures,
|
ConcurrentDictionary<ulong, ScanCapture> captures,
|
||||||
BluetoothLEScanningMode mode,
|
BluetoothLEScanningMode mode,
|
||||||
@@ -360,7 +364,8 @@ public sealed class BleDeviceService : IBleTransport
|
|||||||
|
|
||||||
if (!device.Properties.TryGetValue("System.Devices.Aep.DeviceAddress", out var addressValue)
|
if (!device.Properties.TryGetValue("System.Devices.Aep.DeviceAddress", out var addressValue)
|
||||||
|| addressValue is not string addressText
|
|| addressValue is not string addressText
|
||||||
|| !TryParseBluetoothAddress(addressText, out var address))
|
|| !TryParseBluetoothAddress(addressText, out var address)
|
||||||
|
|| !IsSupportedAddress(address))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,11 @@ public sealed class MultiDeviceController : IAsyncDisposable
|
|||||||
|
|
||||||
public async Task<ConnectedDeviceViewModel> ConnectAsync(BleScanResult device, CancellationToken cancellationToken = default)
|
public async Task<ConnectedDeviceViewModel> ConnectAsync(BleScanResult device, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
if (!BleDeviceService.IsSupportedAddress(device.AddressValue))
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Desteklenmeyen cihaz adresi: {device.BluetoothAddress}", nameof(device));
|
||||||
|
}
|
||||||
|
|
||||||
DeviceConnectionContext? existing;
|
DeviceConnectionContext? existing;
|
||||||
lock (_stateLock)
|
lock (_stateLock)
|
||||||
{
|
{
|
||||||
@@ -583,6 +588,11 @@ public sealed class MultiDeviceController : IAsyncDisposable
|
|||||||
|
|
||||||
private void UpsertKnownDevice(BleScanResult device)
|
private void UpsertKnownDevice(BleScanResult device)
|
||||||
{
|
{
|
||||||
|
if (!BleDeviceService.IsSupportedAddress(device.AddressValue))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var alias = GetAlias(device.BluetoothAddress);
|
var alias = GetAlias(device.BluetoothAddress);
|
||||||
var profile = new DeviceProfile(
|
var profile = new DeviceProfile(
|
||||||
string.IsNullOrWhiteSpace(alias) ? device.NativeName : alias,
|
string.IsNullOrWhiteSpace(alias) ? device.NativeName : alias,
|
||||||
@@ -675,6 +685,19 @@ public sealed class MultiDeviceController : IAsyncDisposable
|
|||||||
: connections.Any(context => context.ViewModel.ConnectionStatus == DeviceConnectionStatus.Faulted)
|
: connections.Any(context => context.ViewModel.ConnectionStatus == DeviceConnectionStatus.Faulted)
|
||||||
? DeviceConnectionStatus.Faulted
|
? DeviceConnectionStatus.Faulted
|
||||||
: DeviceConnectionStatus.Disconnected;
|
: DeviceConnectionStatus.Disconnected;
|
||||||
|
|
||||||
|
if (State.ConnectionStatus == DeviceConnectionStatus.Faulted
|
||||||
|
&& !State.StatusText.Contains("Hata:", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
var firstFault = connections
|
||||||
|
.Where(context => context.ViewModel.ConnectionStatus == DeviceConnectionStatus.Faulted)
|
||||||
|
.Select(context => context.ViewModel.StatusText)
|
||||||
|
.FirstOrDefault(text => !string.IsNullOrWhiteSpace(text));
|
||||||
|
if (!string.IsNullOrWhiteSpace(firstFault))
|
||||||
|
{
|
||||||
|
State.StatusText = firstFault;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureTargetsAvailable()
|
private void EnsureTargetsAvailable()
|
||||||
@@ -708,7 +731,10 @@ public sealed class MultiDeviceController : IAsyncDisposable
|
|||||||
: $"İşlem başarısız oldu: {firstFailureMessage}";
|
: $"İşlem başarısız oldu: {firstFailureMessage}";
|
||||||
}
|
}
|
||||||
|
|
||||||
return $"{successMessage} {successCount}/{totalCount} hedef başarılı, {failureCount} hata.";
|
var partialMessage = $"{successMessage} {successCount}/{totalCount} hedef başarılı, {failureCount} hata.";
|
||||||
|
return string.IsNullOrWhiteSpace(firstFailureMessage)
|
||||||
|
? partialMessage
|
||||||
|
: $"{partialMessage} Hata: {firstFailureMessage}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class DeviceConnectionContext
|
private sealed class DeviceConnectionContext
|
||||||
|
|||||||
Reference in new issue
Block a user