From 87a9753673924b035c638ebf782c2cba27aa75fb Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Fri, 7 Aug 2026 20:04:04 +0900 Subject: [PATCH] Surface newer server disconnect reasons as distinct DisconnectReason values The protocol defines nine disconnect reasons the public enum had no members for, so they were all reported as unknown. Add members for them and map them in toSDKType. --- .changes/disconnect-reason-members | 1 + lib/src/extensions.dart | 9 +++++ lib/src/types/other.dart | 9 +++++ test/types/disconnect_reason_test.dart | 48 ++++++++++++++++++++++++++ 4 files changed, 67 insertions(+) create mode 100644 .changes/disconnect-reason-members create mode 100644 test/types/disconnect_reason_test.dart diff --git a/.changes/disconnect-reason-members b/.changes/disconnect-reason-members new file mode 100644 index 000000000..1cb678d6d --- /dev/null +++ b/.changes/disconnect-reason-members @@ -0,0 +1 @@ +minor type="added" "DisconnectReason gained members for the newer server reasons (roomClosed, migration, signalClose, userUnavailable, userRejected, sipTrunkFailure, connectionTimeout, mediaFailure, agentError), previously reported as unknown" diff --git a/lib/src/extensions.dart b/lib/src/extensions.dart index 171dfe799..ddbcb247c 100644 --- a/lib/src/extensions.dart +++ b/lib/src/extensions.dart @@ -249,6 +249,15 @@ extension DisconnectReasonExt on lk_models.DisconnectReason { lk_models.DisconnectReason.ROOM_DELETED => DisconnectReason.roomDeleted, lk_models.DisconnectReason.STATE_MISMATCH => DisconnectReason.stateMismatch, lk_models.DisconnectReason.JOIN_FAILURE => DisconnectReason.joinFailure, + lk_models.DisconnectReason.MIGRATION => DisconnectReason.migration, + lk_models.DisconnectReason.SIGNAL_CLOSE => DisconnectReason.signalClose, + lk_models.DisconnectReason.ROOM_CLOSED => DisconnectReason.roomClosed, + lk_models.DisconnectReason.USER_UNAVAILABLE => DisconnectReason.userUnavailable, + lk_models.DisconnectReason.USER_REJECTED => DisconnectReason.userRejected, + lk_models.DisconnectReason.SIP_TRUNK_FAILURE => DisconnectReason.sipTrunkFailure, + lk_models.DisconnectReason.CONNECTION_TIMEOUT => DisconnectReason.connectionTimeout, + lk_models.DisconnectReason.MEDIA_FAILURE => DisconnectReason.mediaFailure, + lk_models.DisconnectReason.AGENT_ERROR => DisconnectReason.agentError, _ => DisconnectReason.unknown, }; } diff --git a/lib/src/types/other.dart b/lib/src/types/other.dart index 98cf6be0a..ecbf1ea0f 100644 --- a/lib/src/types/other.dart +++ b/lib/src/types/other.dart @@ -161,6 +161,15 @@ enum DisconnectReason { disconnected, signalingConnectionFailure, reconnectAttemptsExceeded, + migration, + signalClose, + roomClosed, + userUnavailable, + userRejected, + sipTrunkFailure, + connectionTimeout, + mediaFailure, + agentError, } /// The reason why a track failed to publish. diff --git a/test/types/disconnect_reason_test.dart b/test/types/disconnect_reason_test.dart new file mode 100644 index 000000000..80168be03 --- /dev/null +++ b/test/types/disconnect_reason_test.dart @@ -0,0 +1,48 @@ +// Copyright 2026 LiveKit, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'package:flutter_test/flutter_test.dart'; + +import 'package:livekit_client/src/extensions.dart'; +import 'package:livekit_client/src/proto/livekit_models.pb.dart' as lk_models; +import 'package:livekit_client/src/types/other.dart'; + +void main() { + group('DisconnectReason.toSDKType', () { + test('maps every proto value to a distinct SDK value', () { + final mapped = {}; + for (final reason in lk_models.DisconnectReason.values) { + final sdkReason = reason.toSDKType(); + expect( + mapped.contains(sdkReason), + isFalse, + reason: '$reason maps to $sdkReason which is already used by another proto value', + ); + mapped.add(sdkReason); + } + }); + + test('maps newer server reasons to their own members', () { + expect(lk_models.DisconnectReason.ROOM_CLOSED.toSDKType(), DisconnectReason.roomClosed); + expect(lk_models.DisconnectReason.MIGRATION.toSDKType(), DisconnectReason.migration); + expect(lk_models.DisconnectReason.SIGNAL_CLOSE.toSDKType(), DisconnectReason.signalClose); + expect(lk_models.DisconnectReason.USER_UNAVAILABLE.toSDKType(), DisconnectReason.userUnavailable); + expect(lk_models.DisconnectReason.USER_REJECTED.toSDKType(), DisconnectReason.userRejected); + expect(lk_models.DisconnectReason.SIP_TRUNK_FAILURE.toSDKType(), DisconnectReason.sipTrunkFailure); + expect(lk_models.DisconnectReason.CONNECTION_TIMEOUT.toSDKType(), DisconnectReason.connectionTimeout); + expect(lk_models.DisconnectReason.MEDIA_FAILURE.toSDKType(), DisconnectReason.mediaFailure); + expect(lk_models.DisconnectReason.AGENT_ERROR.toSDKType(), DisconnectReason.agentError); + }); + }); +}