1- import 'dart:async' ;
2-
3- import 'package:meta/meta.dart' ;
4- import 'package:rxdart/rxdart.dart' ;
51import 'package:stream_core/stream_core.dart' ;
62
73import '../stream_feeds.dart' ;
8- import 'generated/api/api.dart' as api;
9- import 'repositories.dart' ;
10- import 'utils/endpoint_config.dart' ;
11- import 'ws/feeds_ws_event.dart' ;
4+ import 'internal_feeds_client.dart' ;
125
13- class FeedsClient {
14- FeedsClient ({
15- required this . apiKey,
16- required this . user,
6+ abstract interface class FeedsClient {
7+ factory FeedsClient ({
8+ required String apiKey,
9+ required User user,
1710 String ? userToken,
1811 TokenProvider ? userTokenProvider,
19- this .config = const FeedsConfig (),
20- FeedsClientEnvironment environment = const FeedsClientEnvironment (),
21- }) : assert (
22- userToken != null || userTokenProvider != null ,
23- 'Provide either a user token or a user token provider, or both' ,
24- ) {
25- tokenManager = userTokenProvider != null
26- ? TokenManager .provider (
27- user: user,
28- provider: userTokenProvider,
29- token: userToken,
30- )
31- : TokenManager .static (user: user, token: userToken ?? '' );
32-
33- // TODO: fill with correct values
34- final systemEnvironmentManager = SystemEnvironmentManager (
35- environment: const SystemEnvironment (
36- sdkName: 'stream-feeds-dart' ,
37- sdkIdentifier: 'dart' ,
38- sdkVersion: '0.1.0' ,
39- ),
40- );
41-
42- apiClient = api.DefaultApi (
43- CoreHttpClient (
44- apiKey,
45- systemEnvironmentManager: systemEnvironmentManager,
46- options: HttpClientOptions (baseUrl: endpointConfig.baseFeedsUrl),
47- connectionIdProvider: () => webSocketClient.connectionId,
48- tokenManager: tokenManager,
49- ),
50- );
51- final websocketUri = Uri .parse (endpointConfig.wsEndpoint).replace (
52- queryParameters: < String , String > {
53- 'api_key' : apiKey,
54- 'stream-auth-type' : 'jwt' ,
55- 'X-Stream-Client' : 'stream-feeds-dart' ,
56- },
57- );
58-
59- webSocketClient = environment.createWebSocketClient (
60- url: websocketUri.toString (),
61- eventDecoder: FeedsWsEvent .fromEventObject,
62- onConnectionEstablished: _authenticate,
63- );
64-
65- feedsRepository = FeedsRepository (apiClient: apiClient);
66- }
67-
68- final String apiKey;
69- final User user;
70- late final TokenManager tokenManager;
71- final FeedsConfig config;
72-
73- late final api.DefaultApi apiClient;
74-
75- @internal
76- late final FeedsRepository feedsRepository;
77-
78- static const endpointConfig = EndpointConfig .production;
79- late final WebSocketClient webSocketClient;
80- ConnectionRecoveryHandler ? connectionRecoveryHandler;
81- Stream <FeedsWsEvent > get feedsEvents =>
82- webSocketClient.events.asStream ().whereType <FeedsWsEvent >();
83-
84- Completer <void >? _connectionCompleter;
85- StreamSubscription <WebSocketConnectionState >? _connectionSubscription;
12+ FeedsConfig config = const FeedsConfig (),
13+ }) =>
14+ InternalFeedsClient (
15+ apiKey: apiKey,
16+ user: user,
17+ userToken: userToken,
18+ userTokenProvider: userTokenProvider,
19+ config: config,
20+ );
8621
8722 /// Connects to the feeds websocket.
8823 /// Future will complete when the connection is established and the user is authenticated.
8924 /// If the authentication fails, the future will complete with an error.
90- Future <void > connect () async {
91- webSocketClient.connect ();
92-
93- _connectionSubscription =
94- webSocketClient.connectionStateStream.listen (_onConnectionStateChanged);
95-
96- connectionRecoveryHandler = DefaultConnectionRecoveryHandler (
97- client: webSocketClient,
98- networkMonitor: config.networkMonitor,
99- );
100-
101- _connectionCompleter = Completer <void >();
102- return _connectionCompleter! .future;
103- }
25+ Future <void > connect ();
10426
10527 /// Disconnects from the feeds websocket.
106- /// The FeedsClient should no longer be used after calling this method.
107- void disconnect () {
108- connectionRecoveryHandler? .dispose ();
109- webSocketClient.disconnect ();
110- _connectionSubscription? .cancel ();
111- _connectionCompleter? .complete ();
112- _connectionCompleter = null ;
113- }
114-
115- void dispose () {
116- if (webSocketClient.connectionState is Connected ) {
117- disconnect ();
118- }
119- webSocketClient.dispose ();
120- }
121-
122- void _onConnectionStateChanged (WebSocketConnectionState state) {
123- if (_connectionCompleter != null ) {
124- if (state is Connected ) {
125- _connectionCompleter! .complete ();
126- _connectionCompleter = null ;
127- }
128- if (state is Disconnected ) {
129- _connectionCompleter! .completeError (Exception ('Connection failed' ));
130- _connectionCompleter = null ;
131- }
132- }
133- }
134-
135- Future <void > _authenticate () async {
136- final connectUserRequest = WsAuthMessageRequest (
137- products: ['feeds' ],
138- token: await tokenManager.loadToken (),
139- userDetails: ConnectUserDetailsRequest (
140- id: user.id,
141- name: user.originalName,
142- image: user.imageUrl,
143- customData: user.customData,
144- ),
145- );
28+ void disconnect ();
14629
147- webSocketClient.send (connectUserRequest);
148- }
30+ /// Disposes the FeedsClient.
31+ /// This should be called when the FeedsClient is no longer needed.
32+ /// It will disconnect from the websocket and dispose of the client.
33+ void dispose ();
14934
15035 /// Creates a feed instance based on the provided query.
15136 ///
@@ -154,9 +39,7 @@ class FeedsClient {
15439 ///
15540 /// - Parameter query: The feed query containing the feed identifier and optional configuration
15641 /// - Returns: A [Feed] instance that can be used to interact with the specified feed
157- Feed feed ({required FeedQuery query}) {
158- return Feed (query: query, client: this );
159- }
42+ Feed feed ({required FeedQuery query});
16043}
16144
16245class FeedsConfig {
@@ -166,22 +49,3 @@ class FeedsConfig {
16649
16750 final NetworkMonitor ? networkMonitor;
16851}
169-
170- class FeedsClientEnvironment {
171- const FeedsClientEnvironment ();
172-
173- WebSocketClient createWebSocketClient ({
174- required String url,
175- required EventDecoder eventDecoder,
176- PingReguestBuilder ? pingReguestBuilder,
177- VoidCallback ? onConnectionEstablished,
178- VoidCallback ? onConnected,
179- }) =>
180- WebSocketClient (
181- url: url,
182- eventDecoder: FeedsWsEvent .fromEventObject,
183- pingReguestBuilder: pingReguestBuilder,
184- onConnectionEstablished: onConnectionEstablished,
185- onConnected: onConnected,
186- );
187- }
0 commit comments