diff --git a/packages/stream_chat/lib/src/client/client.dart b/packages/stream_chat/lib/src/client/client.dart index 6b6ae933..b9f2136d 100644 --- a/packages/stream_chat/lib/src/client/client.dart +++ b/packages/stream_chat/lib/src/client/client.dart @@ -25,7 +25,6 @@ import 'package:stream_chat/src/core/models/member.dart'; import 'package:stream_chat/src/core/models/message.dart'; import 'package:stream_chat/src/core/models/own_user.dart'; import 'package:stream_chat/src/core/models/user.dart'; -import 'package:stream_chat/src/core/platform_detector/platform_detector.dart'; import 'package:stream_chat/src/core/util/utils.dart'; import 'package:stream_chat/src/db/chat_persistence_client.dart'; import 'package:stream_chat/src/event_type.dart'; @@ -44,10 +43,6 @@ final _levelEmojiMapper = { Level.SEVERE: '🚨', }; -final _userAgent = 'stream-chat-dart-client-' - '${CurrentPlatform.name}-' - '${PACKAGE_VERSION.split('+')[0]}'; - /// The official Dart client for Stream Chat, /// a service for building chat applications. /// This library can be used on any Dart project and on both mobile and web apps @@ -86,7 +81,7 @@ class StreamChatClient { location: location, connectTimeout: connectTimeout, receiveTimeout: receiveTimeout, - headers: {'X-Stream-Client': _userAgent}, + headers: {'X-Stream-Client': defaultUserAgent}, ); _chatApi = chatApi ?? @@ -106,7 +101,7 @@ class StreamChatClient { tokenManager: _tokenManager, handler: handleEvent, logger: detachedLogger('🔌'), - queryParameters: {'X-Stream-Client': _userAgent}, + queryParameters: {'X-Stream-Client': defaultUserAgent}, ); _retryPolicy = retryPolicy ?? diff --git a/packages/stream_chat/lib/src/core/http/interceptor/user_agent_interceptor.dart b/packages/stream_chat/lib/src/core/http/interceptor/user_agent_interceptor.dart new file mode 100644 index 00000000..3f18dae2 --- /dev/null +++ b/packages/stream_chat/lib/src/core/http/interceptor/user_agent_interceptor.dart @@ -0,0 +1,20 @@ +import 'package:dio/dio.dart'; +import 'package:stream_chat/src/core/platform_detector/platform_detector.dart'; +import 'package:stream_chat/version.dart'; + +/// User agent interceptor that sets the user agent header +class UserAgentInterceptor extends Interceptor { + final _defaultUserAgent = 'stream-chat-dart-client-' + '${CurrentPlatform.name}-' + '${PACKAGE_VERSION.split('+')[0]}'; + + @override + Future onRequest( + RequestOptions options, + RequestInterceptorHandler handler, + ) async { + options.headers['X-Stream-Client'] = + '$_defaultUserAgent-${usedPackage.name}'; + return handler.next(options); + } +} diff --git a/packages/stream_chat/lib/src/core/http/stream_http_client.dart b/packages/stream_chat/lib/src/core/http/stream_http_client.dart index c19cdb8a..3008d40a 100644 --- a/packages/stream_chat/lib/src/core/http/stream_http_client.dart +++ b/packages/stream_chat/lib/src/core/http/stream_http_client.dart @@ -8,6 +8,7 @@ import 'package:stream_chat/src/core/http/connection_id_manager.dart'; import 'package:stream_chat/src/core/http/interceptor/auth_interceptor.dart'; import 'package:stream_chat/src/core/http/interceptor/connection_id_interceptor.dart'; import 'package:stream_chat/src/core/http/interceptor/logging_interceptor.dart'; +import 'package:stream_chat/src/core/http/interceptor/user_agent_interceptor.dart'; import 'package:stream_chat/src/core/http/stream_chat_dio_error.dart'; import 'package:stream_chat/src/core/http/token_manager.dart'; import 'package:stream_chat/src/location.dart'; @@ -41,6 +42,7 @@ class StreamHttpClient { ..._options.headers, } ..interceptors.addAll([ + UserAgentInterceptor(), if (tokenManager != null) AuthInterceptor(this, tokenManager), if (connectionIdManager != null) ConnectionIdInterceptor(connectionIdManager), diff --git a/packages/stream_chat/lib/version.dart b/packages/stream_chat/lib/version.dart index c839a929..6eafab42 100644 --- a/packages/stream_chat/lib/version.dart +++ b/packages/stream_chat/lib/version.dart @@ -1,6 +1,40 @@ import 'package:stream_chat/src/client/client.dart'; +import 'package:stream_chat/src/core/platform_detector/platform_detector.dart'; /// Current package version /// Used in [StreamChatClient] to build the `x-stream-client` header // ignore: constant_identifier_names const PACKAGE_VERSION = '3.2.0'; + +/// Default user agent used for the 'x-stream-client' header +final defaultUserAgent = 'stream-chat-dart-client-' + '${CurrentPlatform.name}-' + '${PACKAGE_VERSION.split('+')[0]}'; + +/// Current used package +/// This is used to set the `x-stream-client` header using info about +/// the package in use +/// For example: llc/core/ui +Package usedPackage = Package.llc; + +/// Possible packages +enum Package { + /// The Low Level Client + llc, + + /// The Core package + core, + + /// The UI package + ui, +} + +/// +extension XPackage on Package { + /// + String get name => { + Package.llc: 'llc', + Package.core: 'core', + Package.ui: 'ui', + }[this]!; +} diff --git a/packages/stream_chat_flutter/lib/src/stream_chat.dart b/packages/stream_chat_flutter/lib/src/stream_chat.dart index ba8bcf64..a2a40d0d 100644 --- a/packages/stream_chat_flutter/lib/src/stream_chat.dart +++ b/packages/stream_chat_flutter/lib/src/stream_chat.dart @@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_portal/flutter_portal.dart'; import 'package:jiffy/jiffy.dart'; +import 'package:stream_chat/version.dart'; import 'package:stream_chat_flutter/src/stream_chat_theme.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; @@ -110,7 +111,12 @@ class StreamChatState extends State { onBackgroundEventReceived: widget.onBackgroundEventReceived, backgroundKeepAlive: widget.backgroundKeepAlive, connectivityStream: widget.connectivityStream, - child: widget.child ?? const Offstage(), + child: Builder( + builder: (context) { + usedPackage = Package.ui; + return widget.child ?? const Offstage(); + }, + ), ), ); }, diff --git a/packages/stream_chat_flutter_core/example/lib/main.dart b/packages/stream_chat_flutter_core/example/lib/main.dart index 31410e63..e4739161 100644 --- a/packages/stream_chat_flutter_core/example/lib/main.dart +++ b/packages/stream_chat_flutter_core/example/lib/main.dart @@ -4,7 +4,7 @@ import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; Future main() async { /// Create a new instance of [StreamChatClient] passing the apikey obtained /// from your project dashboard. - final client = StreamChatClient('b67pax5b2wdq'); + final client = StreamChatClient('b67pax5b2wdq', logLevel: Level.INFO); /// Set the current user. In a production scenario, this should be done using /// a backend to generate a user token using our server SDK. @@ -120,7 +120,7 @@ class HomeScreen extends StatelessWidget { itemBuilder: (BuildContext context, int index) { final _item = channels[index]; return ListTile( - title: Text(_item.name!), + title: Text(_item.name ?? ''), subtitle: StreamBuilder( stream: _item.state!.lastMessageStream, initialData: _item.state!.lastMessage, diff --git a/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart b/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart index 3d07b3c7..ce781c71 100644 --- a/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart +++ b/packages/stream_chat_flutter_core/lib/src/stream_chat_core.dart @@ -4,6 +4,7 @@ import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat/stream_chat.dart'; +import 'package:stream_chat/version.dart'; import 'package:stream_chat_flutter_core/src/typedef.dart'; /// Widget used to provide information about the chat to the widget tree. @@ -89,6 +90,11 @@ class StreamChatCore extends StatefulWidget { /// State class associated with [StreamChatCore]. class StreamChatCoreState extends State with WidgetsBindingObserver { + /// Constructor used for creating a new instance of [StreamChatCoreState]. + StreamChatCoreState() { + usedPackage = Package.core; + } + /// Initialized client used throughout the application. StreamChatClient get client => widget.client;