Make stream_chat_persistence a add on dependency instead of shipping it with the llc

Signed-off-by: Sahil Kumar <[email protected]>
This commit is contained in:
Sahil Kumar
2021-01-27 12:52:37 +05:30
parent f48b7c8882
commit 1521558304
16 changed files with 126 additions and 187 deletions
+10 -8
View File
@@ -419,7 +419,7 @@ class Channel {
} }
} }
await _client.chatPersistence?.deleteMessageById(messageId); await _client.chatPersistenceClient?.deleteMessageById(messageId);
} }
return res; return res;
@@ -487,7 +487,7 @@ class Channel {
PaginationParams options, { PaginationParams options, {
bool preferOffline = false, bool preferOffline = false,
}) async { }) async {
final cachedReplies = await _client.chatPersistence?.getReplies( final cachedReplies = await _client.chatPersistenceClient?.getReplies(
parentId, parentId,
lessThan: options?.lessThan, lessThan: options?.lessThan,
); );
@@ -603,7 +603,8 @@ class Channel {
} }
if (preferOffline && cid != null) { if (preferOffline && cid != null) {
final updatedState = await _client.chatPersistence?.getChannelStateByCid( final updatedState =
await _client.chatPersistenceClient?.getChannelStateByCid(
cid, cid,
messagePagination: messagesPagination, messagePagination: messagesPagination,
); );
@@ -730,7 +731,7 @@ class Channel {
if (clearHistory == true) { if (clearHistory == true) {
state.truncate(); state.truncate();
await _client.chatPersistence?.deleteMessageByCid(_cid); await _client.chatPersistenceClient?.deleteMessageByCid(_cid);
} }
return _client.decode(response.data, EmptyResponse.fromJson); return _client.decode(response.data, EmptyResponse.fromJson);
@@ -869,7 +870,7 @@ class ChannelClientState {
_computeInitialUnread(); _computeInitialUnread();
_channel._client.chatPersistence _channel._client.chatPersistenceClient
?.getChannelThreads(_channel.cid) ?.getChannelThreads(_channel.cid)
?.then((threads) { ?.then((threads) {
_threads = threads; _threads = threads;
@@ -947,7 +948,8 @@ class ChannelClientState {
.on(EventType.channelTruncated, EventType.notificationChannelTruncated) .on(EventType.channelTruncated, EventType.notificationChannelTruncated)
.listen((event) async { .listen((event) async {
final channel = event.channel; final channel = event.channel;
await _channel._client.chatPersistence?.deleteMessageByCid(channel.cid); await _channel._client.chatPersistenceClient
?.deleteMessageByCid(channel.cid);
truncate(); truncate();
})); }));
} }
@@ -1401,7 +1403,7 @@ class ChannelClientState {
set _channelState(ChannelState v) { set _channelState(ChannelState v) {
_channelStateController.add(v); _channelStateController.add(v);
_channel._client.chatPersistence?.updateChannelState(v); _channel._client.chatPersistenceClient?.updateChannelState(v);
} }
/// The channel threads related to this channel /// The channel threads related to this channel
@@ -1414,7 +1416,7 @@ class ChannelClientState {
BehaviorSubject.seeded({}); BehaviorSubject.seeded({});
set _threads(Map<String, List<Message>> v) { set _threads(Map<String, List<Message>> v) {
_channel._client.chatPersistence?.updateMessages( _channel._client.chatPersistenceClient?.updateMessages(
_channel.cid, _channel.cid,
v.values.expand((v) => v).toList(), v.values.expand((v) => v).toList(),
); );
+24 -31
View File
@@ -6,7 +6,6 @@ import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:rxdart/rxdart.dart'; import 'package:rxdart/rxdart.dart';
import 'package:stream_chat_persistence/stream_chat_persistence.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:stream_chat/src/api/retry_policy.dart'; import 'package:stream_chat/src/api/retry_policy.dart';
import 'package:stream_chat/src/event_type.dart'; import 'package:stream_chat/src/event_type.dart';
@@ -21,7 +20,7 @@ import 'api/connection_status.dart';
import 'api/requests.dart'; import 'api/requests.dart';
import 'api/responses.dart'; import 'api/responses.dart';
import 'api/websocket.dart'; import 'api/websocket.dart';
import 'db/stream_chat_persistence.dart'; import 'db/chat_persistence_client.dart';
import 'exceptions.dart'; import 'exceptions.dart';
import 'models/event.dart'; import 'models/event.dart';
import 'models/message.dart'; import 'models/message.dart';
@@ -87,7 +86,6 @@ class Client {
this.baseURL = _defaultBaseURL, this.baseURL = _defaultBaseURL,
this.logLevel = Level.WARNING, this.logLevel = Level.WARNING,
this.logHandlerFunction, this.logHandlerFunction,
this.persistenceEnabled = true,
Duration connectTimeout = const Duration(seconds: 6), Duration connectTimeout = const Duration(seconds: 6),
Duration receiveTimeout = const Duration(seconds: 6), Duration receiveTimeout = const Duration(seconds: 6),
Dio httpClient, Dio httpClient,
@@ -111,10 +109,11 @@ class Client {
logger.info('instantiating new client'); logger.info('instantiating new client');
} }
StreamChatPersistence _chatPersistence; /// Client chat persistence client
ChatPersistenceClient chatPersistenceClient;
/// If true chat data will persist on disk /// Whether the chat persistence is available or not
final bool persistenceEnabled; bool get persistenceEnabled => chatPersistenceClient != null;
RetryPolicy _retryPolicy; RetryPolicy _retryPolicy;
@@ -131,9 +130,6 @@ class Client {
/// The amount of time that will pass before disconnecting the client in the background /// The amount of time that will pass before disconnecting the client in the background
final Duration backgroundKeepAlive; final Duration backgroundKeepAlive;
/// Client offline database
StreamChatPersistence get chatPersistence => _chatPersistence;
/// This client state /// This client state
ClientState state; ClientState state;
@@ -345,7 +341,7 @@ class Client {
/// Call this function to dispose the client /// Call this function to dispose the client
void dispose() async { void dispose() async {
await _chatPersistence?.disconnect(); await chatPersistenceClient?.disconnect();
await _disconnect(); await _disconnect();
httpClient.close(); httpClient.close();
await _controller.close(); await _controller.close();
@@ -427,8 +423,8 @@ class Client {
if (!event.isLocal) { if (!event.isLocal) {
if (_synced && event.createdAt != null) { if (_synced && event.createdAt != null) {
await _chatPersistence?.updateConnectionInfo(event); await chatPersistenceClient?.updateConnectionInfo(event);
await _chatPersistence?.updateLastSyncAt(event.createdAt); await chatPersistenceClient?.updateLastSyncAt(event.createdAt);
} }
} }
@@ -459,12 +455,8 @@ class Client {
wsConnectionStatus.value = ConnectionStatus.connecting; wsConnectionStatus.value = ConnectionStatus.connecting;
if (persistenceEnabled && _chatPersistence == null) { if (persistenceEnabled) {
_chatPersistence = StreamChatPersistenceImpl( await chatPersistenceClient.connect('db_${state.user.id}');
state.user.id,
logger: _detachedLogger('💽'),
);
await _chatPersistence.connect();
} }
_ws = WebSocket( _ws = WebSocket(
@@ -514,10 +506,10 @@ class Client {
_ws.connectionStatus.addListener(_connectionStatusListener); _ws.connectionStatus.addListener(_connectionStatusListener);
var event = await _chatPersistence?.getConnectionInfo(); var event = await chatPersistenceClient?.getConnectionInfo();
await _ws.connect().then((e) async { await _ws.connect().then((e) async {
await _chatPersistence?.updateConnectionInfo(e); await chatPersistenceClient?.updateConnectionInfo(e);
event = e; event = e;
await resync(); await resync();
}).catchError((err, stacktrace) { }).catchError((err, stacktrace) {
@@ -532,14 +524,14 @@ class Client {
/// Get the events missed while offline to sync the offline storage /// Get the events missed while offline to sync the offline storage
Future<void> resync([List<String> cids]) async { Future<void> resync([List<String> cids]) async {
final lastSyncAt = await chatPersistence?.getLastSyncAt(); final lastSyncAt = await chatPersistenceClient?.getLastSyncAt();
if (lastSyncAt == null) { if (lastSyncAt == null) {
_synced = true; _synced = true;
return; return;
} }
cids ??= await chatPersistence?.getChannelCids(); cids ??= await chatPersistenceClient?.getChannelCids();
if (cids?.isEmpty == true) { if (cids?.isEmpty == true) {
return; return;
@@ -568,7 +560,7 @@ class Client {
handleEvent(event); handleEvent(event);
}); });
await _chatPersistence?.updateLastSyncAt(DateTime.now()); await chatPersistenceClient?.updateLastSyncAt(DateTime.now());
_synced = true; _synced = true;
} catch (error) { } catch (error) {
logger.severe('Error during resync $error'); logger.severe('Error during resync $error');
@@ -714,7 +706,7 @@ class Client {
channels.add(channel); channels.add(channel);
} else { } else {
final newChannel = Channel.fromState(this, channelState); final newChannel = Channel.fromState(this, channelState);
await _chatPersistence await chatPersistenceClient
?.updateChannelState(newChannel.state.channelState); ?.updateChannelState(newChannel.state.channelState);
newChannel.state?.updateChannelState(channelState); newChannel.state?.updateChannelState(channelState);
newChannels[newChannel.cid] = newChannel; newChannels[newChannel.cid] = newChannel;
@@ -725,7 +717,7 @@ class Client {
state.channels = newChannels; state.channels = newChannels;
await _chatPersistence?.updateChannelQueries( await chatPersistenceClient?.updateChannelQueries(
filter, filter,
res.channels.map((c) => c.channel.cid).toList(), res.channels.map((c) => c.channel.cid).toList(),
paginationParams?.offset == null || paginationParams.offset == 0, paginationParams?.offset == null || paginationParams.offset == 0,
@@ -760,7 +752,7 @@ class Client {
@required List<SortOption> sort, @required List<SortOption> sort,
PaginationParams paginationParams = const PaginationParams(limit: 10), PaginationParams paginationParams = const PaginationParams(limit: 10),
}) async { }) async {
final offlineChannels = await _chatPersistence?.getChannelStates( final offlineChannels = await chatPersistenceClient?.getChannelStates(
filter: filter, filter: filter,
sort: sort, sort: sort,
paginationParams: paginationParams, paginationParams: paginationParams,
@@ -775,7 +767,8 @@ class Client {
return channel; return channel;
} else { } else {
final newChannel = Channel.fromState(this, channelState); final newChannel = Channel.fromState(this, channelState);
_chatPersistence?.updateChannelState(newChannel.state.channelState); chatPersistenceClient
?.updateChannelState(newChannel.state.channelState);
newChannels[newChannel.cid] = newChannel; newChannels[newChannel.cid] = newChannel;
return newChannel; return newChannel;
} }
@@ -938,8 +931,8 @@ class Client {
logger.info( logger.info(
'Disconnecting flushOfflineStorage: $flushChatPersistence; clearUser: $clearUser'); 'Disconnecting flushOfflineStorage: $flushChatPersistence; clearUser: $clearUser');
await _chatPersistence?.disconnect(flush: flushChatPersistence); await chatPersistenceClient?.disconnect(flush: flushChatPersistence);
_chatPersistence = null; chatPersistenceClient = null;
if (clearUser == true) { if (clearUser == true) {
state.dispose(); state.dispose();
@@ -1328,7 +1321,7 @@ class ClientState {
void _listenChannelHidden() { void _listenChannelHidden() {
_subscriptions.add(_client.on(EventType.channelHidden).listen((event) { _subscriptions.add(_client.on(EventType.channelHidden).listen((event) {
_client._chatPersistence?.deleteChannels([event.cid]); _client.chatPersistenceClient?.deleteChannels([event.cid]);
if (channels != null) { if (channels != null) {
channels = channels..removeWhere((cid, ch) => cid == event.cid); channels = channels..removeWhere((cid, ch) => cid == event.cid);
} }
@@ -1353,7 +1346,7 @@ class ClientState {
) )
.listen((Event event) async { .listen((Event event) async {
final eventChannel = event.channel; final eventChannel = event.channel;
await _client._chatPersistence?.deleteChannels([eventChannel.cid]); await _client.chatPersistenceClient?.deleteChannels([eventChannel.cid]);
if (channels != null) { if (channels != null) {
channels = channels..remove(eventChannel.cid); channels = channels..remove(eventChannel.cid);
} }
@@ -9,15 +9,12 @@ import 'package:stream_chat/src/models/read.dart';
import 'package:stream_chat/src/models/user.dart'; import 'package:stream_chat/src/models/user.dart';
/// ///
abstract class StreamChatPersistence { abstract class ChatPersistenceClient {
/// Creates a new connection to the database /// Creates a new connection to the client
Future<void> connect({ Future<void> connect(String name);
bool connectBackground = false,
bool logStatements = false,
});
/// Closes the database instance /// Closes the client connection
/// If [flush] is true, the database data will be deleted /// If [flush] is true, the data will also be deleted
Future<void> disconnect({bool flush = false}); Future<void> disconnect({bool flush = false});
/// Get stored replies by messageId /// Get stored replies by messageId
+14 -40
View File
@@ -1,12 +1,11 @@
import 'dart:convert'; import 'dart:convert';
import 'package:logging/logging.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:stream_chat/src/api/responses.dart'; import 'package:stream_chat/src/api/responses.dart';
import 'package:stream_chat/src/models/channel_model.dart'; import 'package:stream_chat/src/models/channel_model.dart';
import 'package:stream_chat/src/models/channel_state.dart'; import 'package:stream_chat/src/models/channel_state.dart';
import 'package:stream_chat/src/models/message.dart'; import 'package:stream_chat/src/models/message.dart';
import 'package:stream_chat_persistence/stream_chat_persistence.dart'; import 'package:meta/meta.dart';
import 'client.dart'; import 'client.dart';
import 'models/own_user.dart'; import 'models/own_user.dart';
@@ -20,21 +19,13 @@ class NotificationService {
) async { ) async {
if (message != null && client.persistenceEnabled) { if (message != null && client.persistenceEnabled) {
if (client?.state?.channels == null) { if (client?.state?.channels == null) {
final sharedPreferences = await _getSharedPreferences(); final chatPersistenceClient = client.chatPersistenceClient;
final userId = sharedPreferences.getString(KEY_USER_ID); await chatPersistenceClient.updateChannelState(
final chatPersistence = StreamChatPersistenceImpl(
userId,
logger: Logger('💽'),
);
await chatPersistence.connect();
await chatPersistence.updateChannelState(
ChannelState( ChannelState(
channel: channelModel, channel: channelModel,
messages: [message], messages: [message],
), ),
); );
await chatPersistence.disconnect();
} else { } else {
final channel = client.state.channels[channelModel.cid]; final channel = client.state.channels[channelModel.cid];
channel.state.updateChannelState( channel.state.updateChannelState(
@@ -56,14 +47,11 @@ class NotificationService {
/// Gets the message using the client without storing it in the offline storage /// Gets the message using the client without storing it in the offline storage
/// It returns an object containing the information about the message and the channel /// It returns an object containing the information about the message and the channel
static Future<GetMessageResponse> getMessage(String messageId) async { static Future<GetMessageResponse> _getMessage(String messageId) async {
final sharedPreferences = await _getSharedPreferences(); final sharedPreferences = await _getSharedPreferences();
final apiKey = sharedPreferences.getString(KEY_API_KEY); final apiKey = sharedPreferences.getString(KEY_API_KEY);
final client = Client( final client = Client(apiKey);
apiKey,
persistenceEnabled: false,
);
final userId = sharedPreferences.getString(KEY_USER_ID); final userId = sharedPreferences.getString(KEY_USER_ID);
final token = sharedPreferences.getString(KEY_TOKEN); final token = sharedPreferences.getString(KEY_TOKEN);
@@ -74,30 +62,16 @@ class NotificationService {
return res; return res;
} }
/// Stores the message in the offline storage /// Gets the message using the client and calls a [storeMessageHandler] callback
static Future<void> storeMessage(GetMessageResponse messageResponse) async { /// with the message if the user wants to save the message in db
final sharedPreferences = await _getSharedPreferences(); ///
final userId = sharedPreferences.getString(KEY_USER_ID);
final chatPersistence = StreamChatPersistenceImpl(
userId,
logger: Logger('💽'),
);
await chatPersistence.connect();
await chatPersistence.updateChannelState(ChannelState(
messages: [messageResponse.message],
channel: messageResponse.channel,
));
await chatPersistence.disconnect();
}
/// Gets the message using the client and stores it in the offline storage
/// It returns an object containing the information about the message and the channel /// It returns an object containing the information about the message and the channel
static Future<GetMessageResponse> getAndStoreMessage(String messageId) async { static Future<GetMessageResponse> getAndStoreMessage({
final getMessageResponse = await getMessage(messageId); @required String messageId,
await storeMessage(getMessageResponse); @required Future<void> Function(GetMessageResponse) storeMessageHandler,
}) async {
final getMessageResponse = await _getMessage(messageId);
await storeMessageHandler(getMessageResponse);
return getMessageResponse; return getMessageResponse;
} }
+1 -1
View File
@@ -27,4 +27,4 @@ export './src/models/reaction.dart';
export './src/models/read.dart'; export './src/models/read.dart';
export './src/models/user.dart'; export './src/models/user.dart';
export './src/notifications.dart'; export './src/notifications.dart';
export './src/db/stream_chat_persistence.dart'; export './src/db/chat_persistence_client.dart';
@@ -8,9 +8,11 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'package:stream_chat_persistence/stream_chat_persistence.dart';
import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart';
import 'choose_user_page.dart'; import 'choose_user_page.dart';
import 'main.dart';
import 'notifications_service.dart'; import 'notifications_service.dart';
class AdvancedOptionsPage extends StatefulWidget { class AdvancedOptionsPage extends StatefulWidget {
@@ -278,8 +280,7 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
showLocalNotification: (!kIsWeb && Platform.isAndroid) showLocalNotification: (!kIsWeb && Platform.isAndroid)
? showLocalNotification ? showLocalNotification
: null, : null,
persistenceEnabled: true, )..chatPersistenceClient = chatPersistentClient;
);
try { try {
await client.setUser( await client.setUser(
@@ -320,72 +321,13 @@ class _AdvancedOptionsPageState extends State<AdvancedOptionsPage> {
return; return;
} }
if (!kIsWeb) {
initNotifications(client);
}
Navigator.pop(context); Navigator.pop(context);
Navigator.pop(context);
await Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) {
return FutureBuilder<StreamingSharedPreferences>(
future: StreamingSharedPreferences.instance,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SizedBox();
}
return PreferenceBuilder<int>(
preference: snapshot.data.getInt(
'theme',
defaultValue: 0,
),
builder: (context, snapshot) => MaterialApp(
builder: (context, child) {
return StreamChat(
client: client,
child: Builder(
builder: (context) =>
AnnotatedRegion<
SystemUiOverlayStyle>(
child: child,
value: SystemUiOverlayStyle(
systemNavigationBarColor:
StreamChatTheme.of(context)
.colorTheme
.white,
systemNavigationBarIconBrightness:
Theme.of(context)
.brightness ==
Brightness.dark
? Brightness.light
: Brightness.dark,
),
),
),
);
},
debugShowCheckedModeBanner: false,
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: {
-1: ThemeMode.dark,
0: ThemeMode.system,
1: ThemeMode.light,
}[snapshot],
onGenerateRoute: AppRoutes.generateRoute,
initialRoute: client.state.user == null
? Routes.CHOOSE_USER
: Routes.HOME,
),
);
},
);
},
),
);
loading = false; loading = false;
await Navigator.pushReplacementNamed(
context,
Routes.APP,
arguments: client,
);
} }
}, },
), ),
@@ -10,6 +10,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart';
import 'package:stream_chat_persistence/stream_chat_persistence.dart';
import 'package:streaming_shared_preferences/streaming_shared_preferences.dart'; import 'package:streaming_shared_preferences/streaming_shared_preferences.dart';
import 'notifications_service.dart'; import 'notifications_service.dart';
@@ -17,6 +18,11 @@ import 'routes/app_routes.dart';
import 'routes/routes.dart'; import 'routes/routes.dart';
import 'search_text_field.dart'; import 'search_text_field.dart';
final chatPersistentClient = StreamChatPersistenceClient(
logLevel: Level.INFO,
connectionMode: ConnectionMode.background,
);
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
final secureStorage = FlutterSecureStorage(); final secureStorage = FlutterSecureStorage();
@@ -29,8 +35,7 @@ void main() async {
logLevel: Level.INFO, logLevel: Level.INFO,
showLocalNotification: showLocalNotification:
(!kIsWeb && Platform.isAndroid) ? showLocalNotification : null, (!kIsWeb && Platform.isAndroid) ? showLocalNotification : null,
persistenceEnabled: true, )..chatPersistenceClient = chatPersistentClient;
);
if (userId != null) { if (userId != null) {
final token = await secureStorage.read(key: kStreamToken); final token = await secureStorage.read(key: kStreamToken);
@@ -1,5 +1,6 @@
import 'dart:io'; import 'dart:io';
import 'package:example/main.dart';
import 'package:flutter_apns/flutter_apns.dart'; import 'package:flutter_apns/flutter_apns.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart' import 'package:flutter_local_notifications/flutter_local_notifications.dart'
hide Message; hide Message;
@@ -36,8 +37,17 @@ Future backgroundHandler(Map<String, dynamic> notification) async {
print('new notification ${notification}'); print('new notification ${notification}');
final messageId = notification['data']['id']; final messageId = notification['data']['id'];
final notificationData = final notificationData = await NotificationService.getAndStoreMessage(
await NotificationService.getAndStoreMessage(messageId); messageId: messageId,
storeMessageHandler: (messageResponse) {
return chatPersistentClient.updateChannelState(
ChannelState(
messages: [messageResponse.message],
channel: messageResponse.channel,
),
);
},
);
showLocalNotification( showLocalNotification(
notificationData.message, notificationData.message,
@@ -15,6 +15,12 @@ class AppRoutes {
static Route<dynamic> generateRoute(RouteSettings settings) { static Route<dynamic> generateRoute(RouteSettings settings) {
final args = settings.arguments; final args = settings.arguments;
switch (settings.name) { switch (settings.name) {
case Routes.APP:
return MaterialPageRoute(
settings: const RouteSettings(name: Routes.APP),
builder: (_) {
return MyApp(args);
});
case Routes.HOME: case Routes.HOME:
return MaterialPageRoute( return MaterialPageRoute(
settings: const RouteSettings(name: Routes.HOME), settings: const RouteSettings(name: Routes.HOME),
@@ -1,5 +1,6 @@
/// Define all the route names here /// Define all the route names here
class Routes { class Routes {
static const String APP = '/app';
static const String HOME = '/home'; static const String HOME = '/home';
static const String CHOOSE_USER = '/choose_user'; static const String CHOOSE_USER = '/choose_user';
static const String ADVANCED_OPTIONS = '/advance_options'; static const String ADVANCED_OPTIONS = '/advance_options';
@@ -9,8 +9,10 @@ environment:
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
stream_chat_flutter: stream_chat_flutter:
path: ../ path: ../
stream_chat_persistence:
path: ../../stream_chat_persistence
flutter_apns: ^1.4.1 flutter_apns: ^1.4.1
flutter_local_notifications: ^2.0.2 flutter_local_notifications: ^2.0.2
flutter_svg: ^0.19.1 flutter_svg: ^0.19.1
@@ -11,7 +11,7 @@ class SharedDB {
static constructOfflineStorage( static constructOfflineStorage(
String dbName, { String dbName, {
logStatements = false, bool logStatements = false,
}) { }) {
throw 'Unsupported Platform'; throw 'Unsupported Platform';
} }
@@ -1,5 +1,4 @@
import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat/stream_chat.dart';
import 'user_mapper.dart';
import 'package:stream_chat_persistence/src/db/moor_chat_database.dart'; import 'package:stream_chat_persistence/src/db/moor_chat_database.dart';
/// ///
@@ -3,18 +3,30 @@ import 'package:stream_chat/stream_chat.dart';
import 'db/moor_chat_database.dart'; import 'db/moor_chat_database.dart';
import 'db/shared/shared_db.dart'; import 'db/shared/shared_db.dart';
/// Various connection modes on which [StreamChatPersistenceClient] can work
enum ConnectionMode {
/// Connects the [StreamChatPersistenceClient] on a regular/default isolate
regular,
/// Connects the [StreamChatPersistenceClient] on a background isolate
background,
}
/// ///
class StreamChatPersistenceImpl extends StreamChatPersistence { class StreamChatPersistenceClient extends ChatPersistenceClient {
/// ///
StreamChatPersistenceImpl( StreamChatPersistenceClient({
this._userId, { /// Connection mode on which the client will work
Logger logger, ConnectionMode connectionMode = ConnectionMode.regular,
}) : _logger = logger, Level logLevel = Level.WARNING,
assert(_userId != null); }) : assert(connectionMode != null),
assert(logLevel != null),
_connectionMode = connectionMode,
_logger = Logger.detached('💽')..level = logLevel;
final String _userId;
final Logger _logger;
MoorChatDatabase _db; MoorChatDatabase _db;
final Logger _logger;
final ConnectionMode _connectionMode;
bool get _debugAssertConnected { bool get _debugAssertConnected {
assert(() { assert(() {
@@ -30,27 +42,22 @@ class StreamChatPersistenceImpl extends StreamChatPersistence {
} }
@override @override
Future<void> connect({ Future<void> connect(String name) async {
bool connectBackground = false,
bool logStatements = false,
}) async {
if (_db != null) { if (_db != null) {
throw Exception( throw Exception(
'An instance of StreamChatDatabase is already connected.\n' 'An instance of StreamChatDatabase is already connected.\n'
'disconnect the previous instance before connecting again.', 'disconnect the previous instance before connecting again.',
); );
} }
switch (_connectionMode) {
final dbName = 'db_$_userId'; case ConnectionMode.regular:
if (connectBackground) { _logger.info('Connecting on a regular isolate');
_logger?.info('Connecting on background isolate'); _db = MoorChatDatabase(name);
_db = await SharedDB.constructOfflineStorage( return;
dbName, case ConnectionMode.background:
logStatements: logStatements, _logger.info('Connecting on background isolate');
); _db = await SharedDB.constructOfflineStorage(name);
} else { return;
_logger?.info('Connecting on a regular isolate');
_db = MoorChatDatabase(dbName, logStatements: logStatements);
} }
} }
@@ -202,9 +209,9 @@ class StreamChatPersistenceImpl extends StreamChatPersistence {
@override @override
Future<void> disconnect({bool flush = false}) async { Future<void> disconnect({bool flush = false}) async {
if (_db != null) { if (_db != null) {
_logger?.info('Disconnecting'); _logger.info('Disconnecting');
if (flush) { if (flush) {
_logger?.info('Flushing'); _logger.info('Flushing');
await _db.batch((batch) { await _db.batch((batch) {
_db.allTables.forEach((table) { _db.allTables.forEach((table) {
_db.delete(table).go(); _db.delete(table).go();
@@ -1,3 +1,3 @@
library stream_chat_persistence; library stream_chat_persistence;
export 'src/stream_chat_persistence_impl.dart'; export 'src/stream_chat_persistence_client.dart';
@@ -11,6 +11,7 @@ dependencies:
moor: ^3.4.0 moor: ^3.4.0
path: ^1.7.0 path: ^1.7.0
path_provider: ^1.6.27 path_provider: ^1.6.27
sqlite3_flutter_libs: ^0.3.0
stream_chat: stream_chat:
path: ../dart_client path: ../dart_client