Skip to content

Commit f93bc66

Browse files
refactor: consolidate WebLoginStartResult and WebLoginWaitResult into WebLoginResult
WebLoginStartResult and WebLoginWaitResult were byte-for-byte identical: both had the same 5 properties (Message, QrDataUrl, Connected, Error, RawResponse). The method names (WebLoginStartAsync / WebLoginWaitAsync) already distinguish the two flows semantically, so maintaining two separate types added no value. Replace both with a single WebLoginResult class. Update IOperatorGatewayClient, OpenClawGatewayClient, and the FakeOperatorGatewayClient test stub accordingly. ChannelsPage.xaml.cs uses both via property access with inferred types and required no changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 71d2497 commit f93bc66

4 files changed

Lines changed: 16 additions & 26 deletions

File tree

src/OpenClaw.Shared/ChannelsSnapshot.cs

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -234,22 +234,12 @@ public sealed class IMessageChannelStatus
234234

235235
// ─── Web login (QR linking) ──────────────────────────────────────────────────
236236

237-
/// <summary>Result of <c>web.login.start</c> — a QR or status for a channel.</summary>
238-
public sealed class WebLoginStartResult
239-
{
240-
public string? Message { get; init; }
241-
public string? QrDataUrl { get; init; }
242-
public bool Connected { get; init; }
243-
244-
/// <summary>Gateway-side error message when the call failed (ok=false), or transport exception. Null on success.</summary>
245-
public string? Error { get; init; }
246-
247-
/// <summary>Raw JSON of the gateway response (or stringified exception). Used by the diagnostic disclosure in the UI.</summary>
248-
public string? RawResponse { get; init; }
249-
}
250-
251-
/// <summary>Result of <c>web.login.wait</c> — long-poll outcome.</summary>
252-
public sealed class WebLoginWaitResult
237+
/// <summary>
238+
/// Result of a QR/web-login RPC call (<c>web.login.start</c> or <c>web.login.wait</c>).
239+
/// Both calls return an identical wire shape; a single type removes duplication while
240+
/// the calling method name already distinguishes the two flows.
241+
/// </summary>
242+
public sealed class WebLoginResult
253243
{
254244
public string? Message { get; init; }
255245
public string? QrDataUrl { get; init; }

src/OpenClaw.Shared/IOperatorGatewayClient.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ public interface IOperatorGatewayClient
107107
/// <summary>Log out / unlink a channel (whatsapp, telegram). Sends channels.logout { channel }.</summary>
108108
Task<bool> LogoutChannelAsync(string channelName, int timeoutMs = 12000);
109109
/// <summary>Begin a QR linking flow (whatsapp, signal). Sends web.login.start { force, timeoutMs }.</summary>
110-
Task<WebLoginStartResult?> WebLoginStartAsync(bool force = false, int timeoutMs = 30000);
110+
Task<WebLoginResult?> WebLoginStartAsync(bool force = false, int timeoutMs = 30000);
111111
/// <summary>Long-poll for QR linking completion. Sends web.login.wait { currentQrDataUrl, timeoutMs }.</summary>
112-
Task<WebLoginWaitResult?> WebLoginWaitAsync(string? currentQrDataUrl = null, int timeoutMs = 30000);
112+
Task<WebLoginResult?> WebLoginWaitAsync(string? currentQrDataUrl = null, int timeoutMs = 30000);
113113
Task<JsonElement> SendWizardRequestAsync(string method, object? parameters = null, int timeoutMs = 30000);
114114
}

src/OpenClaw.Shared/OpenClawGatewayClient.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,7 +1069,7 @@ public async Task<bool> LogoutChannelAsync(string channelName, int timeoutMs = 1
10691069
}
10701070

10711071
/// <summary>Begin a web/QR linking flow for the current default linking channel.</summary>
1072-
public async Task<WebLoginStartResult?> WebLoginStartAsync(bool force = false, int timeoutMs = 30000)
1072+
public async Task<WebLoginResult?> WebLoginStartAsync(bool force = false, int timeoutMs = 30000)
10731073
{
10741074
if (!IsConnected) return null;
10751075
try
@@ -1078,7 +1078,7 @@ public async Task<bool> LogoutChannelAsync(string channelName, int timeoutMs = 1
10781078
"web.login.start",
10791079
new { force, timeoutMs },
10801080
timeoutMs + 5000);
1081-
return new WebLoginStartResult
1081+
return new WebLoginResult
10821082
{
10831083
Message = response.ValueKind == JsonValueKind.Object && response.TryGetProperty("message", out var m) && m.ValueKind == JsonValueKind.String ? m.GetString() : null,
10841084
QrDataUrl = response.ValueKind == JsonValueKind.Object && response.TryGetProperty("qrDataUrl", out var q) && q.ValueKind == JsonValueKind.String ? q.GetString() : null,
@@ -1092,7 +1092,7 @@ public async Task<bool> LogoutChannelAsync(string channelName, int timeoutMs = 1
10921092
// Return a populated result with the error so the UI can surface
10931093
// it in the diagnostic disclosure. Returning null would lose the
10941094
// gateway's actual reason for failing.
1095-
return new WebLoginStartResult
1095+
return new WebLoginResult
10961096
{
10971097
Error = ex.Message,
10981098
RawResponse = ex.ToString(),
@@ -1101,7 +1101,7 @@ public async Task<bool> LogoutChannelAsync(string channelName, int timeoutMs = 1
11011101
}
11021102

11031103
/// <summary>Long-poll for QR linking completion.</summary>
1104-
public async Task<WebLoginWaitResult?> WebLoginWaitAsync(string? currentQrDataUrl = null, int timeoutMs = 30000)
1104+
public async Task<WebLoginResult?> WebLoginWaitAsync(string? currentQrDataUrl = null, int timeoutMs = 30000)
11051105
{
11061106
if (!IsConnected) return null;
11071107
try
@@ -1110,7 +1110,7 @@ public async Task<bool> LogoutChannelAsync(string channelName, int timeoutMs = 1
11101110
"web.login.wait",
11111111
new { currentQrDataUrl, timeoutMs },
11121112
timeoutMs + 5000);
1113-
return new WebLoginWaitResult
1113+
return new WebLoginResult
11141114
{
11151115
Message = response.ValueKind == JsonValueKind.Object && response.TryGetProperty("message", out var m) && m.ValueKind == JsonValueKind.String ? m.GetString() : null,
11161116
QrDataUrl = response.ValueKind == JsonValueKind.Object && response.TryGetProperty("qrDataUrl", out var q) && q.ValueKind == JsonValueKind.String ? q.GetString() : null,
@@ -1121,7 +1121,7 @@ public async Task<bool> LogoutChannelAsync(string channelName, int timeoutMs = 1
11211121
catch (Exception ex)
11221122
{
11231123
_logger.Warn($"web.login.wait failed: {ex.Message}");
1124-
return new WebLoginWaitResult
1124+
return new WebLoginResult
11251125
{
11261126
Error = ex.Message,
11271127
RawResponse = ex.ToString(),

tests/OpenClaw.Tray.Tests/OnboardingChatBootstrapperTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,8 @@ public Task<NodeRenameResult> NodeRenameAsync(string nodeId, string displayName)
200200
public Task<bool> StopChannelAsync(string channelName) => Task.FromResult(false);
201201
public Task<ChannelsStatusSnapshot?> GetChannelsStatusAsync(bool probe = false, int timeoutMs = 12000) => Task.FromResult<ChannelsStatusSnapshot?>(null);
202202
public Task<bool> LogoutChannelAsync(string channelName, int timeoutMs = 12000) => Task.FromResult(false);
203-
public Task<WebLoginStartResult?> WebLoginStartAsync(bool force = false, int timeoutMs = 30000) => Task.FromResult<WebLoginStartResult?>(null);
204-
public Task<WebLoginWaitResult?> WebLoginWaitAsync(string? currentQrDataUrl = null, int timeoutMs = 30000) => Task.FromResult<WebLoginWaitResult?>(null);
203+
public Task<WebLoginResult?> WebLoginStartAsync(bool force = false, int timeoutMs = 30000) => Task.FromResult<WebLoginResult?>(null);
204+
public Task<WebLoginResult?> WebLoginWaitAsync(string? currentQrDataUrl = null, int timeoutMs = 30000) => Task.FromResult<WebLoginResult?>(null);
205205
public Task<JsonElement> SendWizardRequestAsync(string method, object? parameters = null, int timeoutMs = 30000) => Task.FromResult(default(JsonElement));
206206
}
207207
#pragma warning restore CS0067

0 commit comments

Comments
 (0)