Skip to content

Commit b9e5a16

Browse files
committed
Add option to set authorization credentials without connecting the user. This allows to call GetLatestUnreadCountsAsync in offline mode, without loading the entire chat
1 parent ffd6f92 commit b9e5a16

4 files changed

Lines changed: 50 additions & 24 deletions

File tree

Assets/Plugins/StreamChat/Core/IStreamChatClient.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,18 @@ Task<StreamDeleteChannelsResponse> DeleteMultipleChannelsAsync(IEnumerable<IStre
254254
bool IsLocalUser(IStreamUser messageUser);
255255

256256
/// <summary>
257-
/// Get current state of unread counts for the user. Unread counts mean how many messages and threads are unread in the channels and threads the user is participating in
257+
/// Get current state of unread counts for the user. Unread counts mean how many messages and threads are unread in the channels and threads the user is participating in.
258+
///
259+
/// This method can be used in offline mode as well to poll the latest unread counts without establishing a connection.
260+
/// To use it this way, you need to call the <see cref="SeAuthorizationCredentials"/> method first to set the authorization credentials for the API call.
258261
/// </summary>
259-
/// <returns><see cref="StreamCurrentUnreadCounts"/></returns>
262+
/// <returns><see cref="StreamCurrentUnreadCounts"/>Contains information about unread counts in channels and threads</returns>
260263
Task<StreamCurrentUnreadCounts> GetLatestUnreadCountsAsync();
264+
265+
/// <summary>
266+
/// Set authorization credentials for the client to use when connecting to the API
267+
/// </summary>
268+
/// <param name="authCredentials">Credentials containing: api key, user ID, and a user Token</param>
269+
void SeAuthorizationCredentials(AuthCredentials authCredentials);
261270
}
262271
}

Assets/Plugins/StreamChat/Core/LowLevelClient/IStreamChatLowLevelClient.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,5 +89,11 @@ void SetReconnectStrategySettings(ReconnectStrategy reconnectStrategy, float? ex
8989
Task DisconnectAsync(bool permanent = false);
9090

9191
Task FetchAndProcessEventsSinceLastReceivedEvent(IEnumerable<string> channelCids);
92+
93+
/// <summary>
94+
/// Set authorization credentials for the client to use when connecting to the API
95+
/// </summary>
96+
/// <param name="authCredentials">Credentials containing: api key, user ID, and a user Token</param>
97+
void SeAuthorizationCredentials(AuthCredentials authCredentials);
9298
}
9399
}

Assets/Plugins/StreamChat/Core/LowLevelClient/StreamChatLowLevelClient.cs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -318,13 +318,13 @@ public StreamChatLowLevelClient(AuthCredentials authCredentials, IWebsocketClien
318318

319319
public void ConnectUser(AuthCredentials userAuthCredentials)
320320
{
321-
SetConnectionCredentials(userAuthCredentials);
321+
SeAuthorizationCredentials(userAuthCredentials);
322322
Connect();
323323
}
324324

325325
public void Connect()
326326
{
327-
SetConnectionCredentials(_authCredentials);
327+
SeAuthorizationCredentials(_authCredentials);
328328

329329
if (!ConnectionState.IsValidToConnect())
330330
{
@@ -342,6 +342,18 @@ public void Connect()
342342

343343
_websocketClient.ConnectAsync(connectionUri).LogIfFailed(_logs);
344344
}
345+
346+
public void SeAuthorizationCredentials(AuthCredentials authCredentials)
347+
{
348+
if (authCredentials.IsAnyEmpty())
349+
{
350+
throw new StreamMissingAuthCredentialsException(
351+
"Please provide valid credentials: `Api Key`, 'User id`, `User token`");
352+
}
353+
354+
_authCredentials = authCredentials;
355+
_httpClient.SetDefaultAuthenticationHeader(authCredentials.UserToken);
356+
}
345357

346358
public async Task DisconnectAsync(bool permanent = false)
347359
{
@@ -562,7 +574,7 @@ private async Task RefreshAuthTokenFromProvider()
562574
{
563575
var token = await _tokenProvider.GetTokenAsync(_authCredentials.UserId);
564576
_authCredentials = _authCredentials.CreateWithNewUserToken(token);
565-
SetConnectionCredentials(_authCredentials);
577+
SeAuthorizationCredentials(_authCredentials);
566578

567579
#if STREAM_DEBUG_ENABLED
568580
_logs.Info($"auth token received for user `{_authCredentials.UserId}`: " + token);
@@ -935,18 +947,6 @@ private static string Base64UrlEncode(byte[] input)
935947
.Replace('/', '_')
936948
.Trim('=');
937949

938-
private void SetConnectionCredentials(AuthCredentials credentials)
939-
{
940-
if (credentials.IsAnyEmpty())
941-
{
942-
throw new StreamMissingAuthCredentialsException(
943-
"Please provide valid credentials: `Api Key`, 'User id`, `User token`");
944-
}
945-
946-
_authCredentials = credentials;
947-
_httpClient.SetDefaultAuthenticationHeader(credentials.UserToken);
948-
}
949-
950950
//StreamTodo: make it more clear that we either receive full set of credentials or apiKey, userId and the token provider
951951
private void SetPartialConnectionCredentials(string apiKey, string userId)
952952
{

Assets/Plugins/StreamChat/Core/StreamChatClient.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ public static string CreateDeveloperAuthToken(string userId)
165165
/// <inheritdoc cref="StreamChatLowLevelClient.SanitizeUserId"/>
166166
public static string SanitizeUserId(string userId) => StreamChatLowLevelClient.SanitizeUserId(userId);
167167

168+
public void SeAuthorizationCredentials(AuthCredentials authCredentials)
169+
=> InternalLowLevelClient.SeAuthorizationCredentials(authCredentials);
170+
168171
public Task<IStreamLocalUserData> ConnectUserAsync(AuthCredentials userAuthCredentials,
169172
CancellationToken cancellationToken = default)
170173
{
@@ -219,7 +222,7 @@ public async Task<StreamCurrentUnreadCounts> GetLatestUnreadCountsAsync()
219222
{
220223
var dto = await InternalLowLevelClient.InternalChannelApi.GetUnreadCountsAsync();
221224
var response = dto.ToDomain<WrappedUnreadCountsResponseInternalDTO, StreamCurrentUnreadCounts>();
222-
225+
223226
_localUserData.TryUpdateFromDto<WrappedUnreadCountsResponseInternalDTO, StreamLocalUserData>(dto, _cache);
224227

225228
return response;
@@ -453,7 +456,8 @@ public async Task<IEnumerable<IStreamUser>> UpsertUsers(IEnumerable<StreamUserUp
453456
StreamAsserts.AssertNotNullOrEmpty(userRequests, nameof(userRequests));
454457

455458
//StreamTodo: items could be null
456-
var requestDtos = userRequests.Select(_ => _.TrySaveToDto<UserRequestInternalDTO>()).ToDictionary(_ => _.Id, _ => _);
459+
var requestDtos = userRequests.Select(_ => _.TrySaveToDto<UserRequestInternalDTO>())
460+
.ToDictionary(_ => _.Id, _ => _);
457461

458462
var response = await InternalLowLevelClient.InternalUserApi.UpsertManyUsersAsync(
459463
new UpdateUsersRequestInternalDTO
@@ -720,7 +724,7 @@ private void TryCancelWaitingForUserConnection()
720724
_connectUserTaskSource.TrySetCanceled();
721725
}
722726
}
723-
727+
724728
private async Task InternalGetOrCreateChannelAsync(ChannelType channelType, string channelId)
725729
{
726730
#if STREAM_TESTS_ENABLED
@@ -749,7 +753,8 @@ private async Task InternalGetOrCreateChannelAsync(ChannelType channelType, stri
749753

750754
var delay = 4 * i;
751755
#if STREAM_TESTS_ENABLED
752-
_logs.Warning($"InternalGetOrCreateChannelAsync attempt failed due to rate limit. Wait {delay} seconds and try again");
756+
_logs.Warning(
757+
$"InternalGetOrCreateChannelAsync attempt failed due to rate limit. Wait {delay} seconds and try again");
753758
#endif
754759
//StreamTodo: pass CancellationToken
755760
await Task.Delay(delay * 1000);
@@ -1144,7 +1149,9 @@ private void OnReactionReceived(ReactionNewEventInternalDTO eventDto)
11441149

11451150
if (_cache.Messages.TryGet(eventDto.Message.Id, out var message))
11461151
{
1147-
var reaction = new StreamReaction().TryLoadFromDto<ReactionInternalDTO, StreamReaction>(eventDto.Reaction, _cache);
1152+
var reaction
1153+
= new StreamReaction().TryLoadFromDto<ReactionInternalDTO, StreamReaction>(eventDto.Reaction,
1154+
_cache);
11481155
message.HandleReactionNewEvent(eventDto, channel, reaction);
11491156
channel.InternalNotifyReactionReceived(message, reaction);
11501157
}
@@ -1159,7 +1166,9 @@ private void OnReactionUpdated(ReactionUpdatedEventInternalDTO eventDto)
11591166

11601167
if (_cache.Messages.TryGet(eventDto.Message.Id, out var message))
11611168
{
1162-
var reaction = new StreamReaction().TryLoadFromDto<ReactionInternalDTO, StreamReaction>(eventDto.Reaction, _cache);
1169+
var reaction
1170+
= new StreamReaction().TryLoadFromDto<ReactionInternalDTO, StreamReaction>(eventDto.Reaction,
1171+
_cache);
11631172
message.HandleReactionUpdatedEvent(eventDto, channel, reaction);
11641173
channel.InternalNotifyReactionUpdated(message, reaction);
11651174
}
@@ -1174,7 +1183,9 @@ private void OnReactionDeleted(ReactionDeletedEventInternalDTO eventDto)
11741183

11751184
if (_cache.Messages.TryGet(eventDto.Message.Id, out var message))
11761185
{
1177-
var reaction = new StreamReaction().TryLoadFromDto<ReactionInternalDTO, StreamReaction>(eventDto.Reaction, _cache);
1186+
var reaction
1187+
= new StreamReaction().TryLoadFromDto<ReactionInternalDTO, StreamReaction>(eventDto.Reaction,
1188+
_cache);
11781189
message.HandleReactionDeletedEvent(eventDto, channel, reaction);
11791190
channel.InternalNotifyReactionDeleted(message, reaction);
11801191
}

0 commit comments

Comments
 (0)