mirror of
https://gitlab.com/mysocialportal/relatica
synced 2024-10-18 13:33:32 +00:00
Initial Connections Repo implementation with memory version ported into MemoryConnectionsRepo
This commit is contained in:
parent
3d6ab6998f
commit
b1e4dbf4cc
6 changed files with 275 additions and 107 deletions
61
lib/data/interfaces/connections_repo_intf.dart
Normal file
61
lib/data/interfaces/connections_repo_intf.dart
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:result_monad/result_monad.dart';
|
||||||
|
|
||||||
|
import '../../models/connection.dart';
|
||||||
|
import '../../models/exec_error.dart';
|
||||||
|
import '../../models/group_data.dart';
|
||||||
|
|
||||||
|
class IConnectionsRepo {
|
||||||
|
void addAllGroups(List<GroupData> groups) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool updateConnectionGroupData(String id, List<GroupData> currentGroups) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearGroups() {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
UnmodifiableListView<GroupData> getMyGroups() {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<List<GroupData>, ExecError> getGroupsForUser(String id) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool addConnection(Connection connection) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool addAllConnections(Iterable<Connection> newConnections) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool updateConnection(Connection connection) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<Connection, ExecError> getById(String id) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<Connection, ExecError> getByName(String name) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<Connection, ExecError> getByProfileUrl(String url) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
UnmodifiableListView<Connection> getMyContacts() {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
|
||||||
|
UnmodifiableListView<Connection> getKnownUsersByName(String name) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
}
|
149
lib/data/memory/memory_connections_repo.dart
Normal file
149
lib/data/memory/memory_connections_repo.dart
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
|
import 'package:result_monad/result_monad.dart';
|
||||||
|
|
||||||
|
import '../../models/connection.dart';
|
||||||
|
import '../../models/exec_error.dart';
|
||||||
|
import '../../models/group_data.dart';
|
||||||
|
import '../interfaces/connections_repo_intf.dart';
|
||||||
|
|
||||||
|
class MemoryConnectionsRepo implements IConnectionsRepo {
|
||||||
|
final _connectionsById = <String, Connection>{};
|
||||||
|
final _connectionsByName = <String, Connection>{};
|
||||||
|
final _connectionsByProfileUrl = <String, Connection>{};
|
||||||
|
final _groupsForConnection = <String, List<GroupData>>{};
|
||||||
|
final _myGroups = <GroupData>{};
|
||||||
|
final _myContacts = <Connection>[];
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool addAllConnections(Iterable<Connection> newConnections) {
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
for (final connection in newConnections) {
|
||||||
|
result &= addConnection(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool addConnection(Connection connection) {
|
||||||
|
if (_connectionsById.containsKey(connection.id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return updateConnection(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
UnmodifiableListView<Connection> getKnownUsersByName(String name) {
|
||||||
|
return UnmodifiableListView(_connectionsByName.values.where((it) {
|
||||||
|
final normalizedHandle = it.handle.toLowerCase();
|
||||||
|
final normalizedName = it.name.toLowerCase();
|
||||||
|
final normalizedQuery = name.toLowerCase();
|
||||||
|
return normalizedHandle.contains(normalizedQuery) ||
|
||||||
|
normalizedName.contains(normalizedQuery);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool updateConnection(Connection connection) {
|
||||||
|
_connectionsById[connection.id] = connection;
|
||||||
|
_connectionsByName[connection.name] = connection;
|
||||||
|
_connectionsByProfileUrl[connection.profileUrl.toString()] = connection;
|
||||||
|
int index = _myContacts.indexWhere((c) => c.id == connection.id);
|
||||||
|
if (index >= 0) {
|
||||||
|
_myContacts.removeAt(index);
|
||||||
|
}
|
||||||
|
switch (connection.status) {
|
||||||
|
case ConnectionStatus.youFollowThem:
|
||||||
|
case ConnectionStatus.theyFollowYou:
|
||||||
|
case ConnectionStatus.mutual:
|
||||||
|
if (index > 0) {
|
||||||
|
_myContacts.insert(index, connection);
|
||||||
|
} else {
|
||||||
|
_myContacts.add(connection);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
UnmodifiableListView<Connection> getMyContacts() {
|
||||||
|
return UnmodifiableListView(_myContacts);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Result<List<GroupData>, ExecError> getGroupsForUser(String id) {
|
||||||
|
if (!_groupsForConnection.containsKey(id)) {
|
||||||
|
return Result.error(ExecError(
|
||||||
|
type: ErrorType.notFound,
|
||||||
|
message: '$id not a known user ID',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.ok(UnmodifiableListView(_groupsForConnection[id]!));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Result<Connection, ExecError> getById(String id) {
|
||||||
|
final result = _connectionsById[id];
|
||||||
|
if (result == null) {
|
||||||
|
return Result.error(ExecError(
|
||||||
|
type: ErrorType.notFound,
|
||||||
|
message: '$id not found',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Result<Connection, ExecError> getByName(String name) {
|
||||||
|
final result = _connectionsByName[name];
|
||||||
|
if (result == null) {
|
||||||
|
return Result.error(ExecError(
|
||||||
|
type: ErrorType.notFound,
|
||||||
|
message: '$name not found',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
UnmodifiableListView<GroupData> getMyGroups() {
|
||||||
|
return UnmodifiableListView(_myGroups);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Result<Connection, ExecError> getByProfileUrl(String url) {
|
||||||
|
final result = _connectionsByProfileUrl[url];
|
||||||
|
if (result == null) {
|
||||||
|
return Result.error(ExecError(
|
||||||
|
type: ErrorType.notFound,
|
||||||
|
message: '$url not found',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return Result.ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void clearGroups() {
|
||||||
|
_myGroups.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void addAllGroups(List<GroupData> groups) {
|
||||||
|
_myGroups.addAll(groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool updateConnectionGroupData(String id, List<GroupData> currentGroups) {
|
||||||
|
_groupsForConnection[id] = currentGroups;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,8 @@ import 'package:multi_trigger_autocomplete/multi_trigger_autocomplete.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:result_monad/result_monad.dart';
|
import 'package:result_monad/result_monad.dart';
|
||||||
|
|
||||||
|
import 'data/interfaces/connections_repo_intf.dart';
|
||||||
|
import 'data/memory/memory_connections_repo.dart';
|
||||||
import 'globals.dart';
|
import 'globals.dart';
|
||||||
import 'models/TimelineIdentifiers.dart';
|
import 'models/TimelineIdentifiers.dart';
|
||||||
import 'routes.dart';
|
import 'routes.dart';
|
||||||
|
@ -44,6 +46,7 @@ void main() async {
|
||||||
await service.initialize();
|
await service.initialize();
|
||||||
return service;
|
return service;
|
||||||
});
|
});
|
||||||
|
getIt.registerSingleton<IConnectionsRepo>(MemoryConnectionsRepo());
|
||||||
getIt.registerLazySingleton<ConnectionsManager>(() => ConnectionsManager());
|
getIt.registerLazySingleton<ConnectionsManager>(() => ConnectionsManager());
|
||||||
getIt.registerLazySingleton<HashtagService>(() => HashtagService());
|
getIt.registerLazySingleton<HashtagService>(() => HashtagService());
|
||||||
getIt.registerSingleton(galleryService);
|
getIt.registerSingleton(galleryService);
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
import 'dart:collection';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:result_monad/result_monad.dart';
|
import 'package:result_monad/result_monad.dart';
|
||||||
|
|
||||||
|
import '../data/interfaces/connections_repo_intf.dart';
|
||||||
import '../globals.dart';
|
import '../globals.dart';
|
||||||
import '../models/connection.dart';
|
import '../models/connection.dart';
|
||||||
import '../models/exec_error.dart';
|
import '../models/exec_error.dart';
|
||||||
|
@ -12,75 +14,26 @@ import 'auth_service.dart';
|
||||||
|
|
||||||
class ConnectionsManager extends ChangeNotifier {
|
class ConnectionsManager extends ChangeNotifier {
|
||||||
static final _logger = Logger('$ConnectionsManager');
|
static final _logger = Logger('$ConnectionsManager');
|
||||||
final _connectionsById = <String, Connection>{};
|
late final IConnectionsRepo repo;
|
||||||
final _connectionsByName = <String, Connection>{};
|
|
||||||
final _connectionsByProfileUrl = <Uri, Connection>{};
|
|
||||||
final _groupsForConnection = <String, List<GroupData>>{};
|
|
||||||
final _myGroups = <GroupData>{};
|
|
||||||
final _myContacts = <Connection>[];
|
|
||||||
var _myContactsInitialized = false;
|
|
||||||
|
|
||||||
int get length => _connectionsById.length;
|
ConnectionsManager() {
|
||||||
|
repo = getIt<IConnectionsRepo>();
|
||||||
void clearCaches() {
|
|
||||||
_connectionsById.clear();
|
|
||||||
_connectionsByName.clear();
|
|
||||||
_connectionsByProfileUrl.clear();
|
|
||||||
_groupsForConnection.clear();
|
|
||||||
_myGroups.clear();
|
|
||||||
_myContacts.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addConnection(Connection connection) {
|
bool addConnection(Connection connection) {
|
||||||
if (_connectionsById.containsKey(connection.id)) {
|
return repo.addConnection(connection);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return updateConnection(connection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Connection> getKnownUsersByName(String name) {
|
List<Connection> getKnownUsersByName(String name) {
|
||||||
return _connectionsByName.values.where((it) {
|
return repo.getKnownUsersByName(name);
|
||||||
final normalizedHandle = it.handle.toLowerCase();
|
|
||||||
final normalizedName = it.name.toLowerCase();
|
|
||||||
final normalizedQuery = name.toLowerCase();
|
|
||||||
return normalizedHandle.contains(normalizedQuery) ||
|
|
||||||
normalizedName.contains(normalizedQuery);
|
|
||||||
}).toList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updateConnection(Connection connection) {
|
bool updateConnection(Connection connection) {
|
||||||
_connectionsById[connection.id] = connection;
|
return repo.updateConnection(connection);
|
||||||
_connectionsByName[connection.name] = connection;
|
|
||||||
_connectionsByProfileUrl[connection.profileUrl] = connection;
|
|
||||||
int index = _myContacts.indexWhere((c) => c.id == connection.id);
|
|
||||||
if (index >= 0) {
|
|
||||||
_myContacts.removeAt(index);
|
|
||||||
}
|
|
||||||
switch (connection.status) {
|
|
||||||
case ConnectionStatus.youFollowThem:
|
|
||||||
case ConnectionStatus.theyFollowYou:
|
|
||||||
case ConnectionStatus.mutual:
|
|
||||||
if (index > 0) {
|
|
||||||
_myContacts.insert(index, connection);
|
|
||||||
} else {
|
|
||||||
_myContacts.add(connection);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addAllConnections(Iterable<Connection> newConnections) {
|
bool addAllConnections(Iterable<Connection> newConnections) {
|
||||||
bool result = true;
|
return repo.addAllConnections(newConnections);
|
||||||
|
|
||||||
for (final connection in newConnections) {
|
|
||||||
result &= addConnection(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> acceptFollowRequest(Connection connection) async {
|
Future<void> acceptFollowRequest(Connection connection) async {
|
||||||
|
@ -178,13 +131,8 @@ class ConnectionsManager extends ChangeNotifier {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Connection> getMyContacts() {
|
UnmodifiableListView<Connection> getMyContacts() {
|
||||||
if (!_myContactsInitialized) {
|
return repo.getMyContacts();
|
||||||
updateAllContacts();
|
|
||||||
_myContactsInitialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _myContacts.toList(growable: false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateAllContacts() async {
|
Future<void> updateAllContacts() async {
|
||||||
|
@ -234,29 +182,34 @@ class ConnectionsManager extends ChangeNotifier {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_myContacts.clear();
|
|
||||||
_myContacts.addAll(results.values);
|
|
||||||
addAllConnections(results.values);
|
addAllConnections(results.values);
|
||||||
_myContacts.sort((c1, c2) => c1.name.compareTo(c2.name));
|
final myContacts = repo.getMyContacts().toList();
|
||||||
_logger.finest('# Contacts:${_myContacts.length}');
|
myContacts.sort((c1, c2) => c1.name.compareTo(c2.name));
|
||||||
|
_logger.finest('# Contacts:${myContacts.length}');
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<GroupData> getMyGroups() {
|
UnmodifiableListView<GroupData> getMyGroups() {
|
||||||
if (_myGroups.isNotEmpty) {
|
final myGroups = repo.getMyGroups();
|
||||||
return _myGroups.toList(growable: false);
|
if (myGroups.isEmpty) {
|
||||||
|
_updateMyGroups(true);
|
||||||
}
|
}
|
||||||
_updateMyGroups(true);
|
|
||||||
return [];
|
return myGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<List<GroupData>, ExecError> getGroupsForUser(String id) {
|
Result<List<GroupData>, ExecError> getGroupsForUser(String id) {
|
||||||
if (!_groupsForConnection.containsKey(id)) {
|
final result = repo.getGroupsForUser(id);
|
||||||
_refreshGroupListData(id, true);
|
if (result.isSuccess) {
|
||||||
return Result.ok([]);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.ok(_groupsForConnection[id]!);
|
if (result.isFailure && result.error.type != ErrorType.notFound) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
_refreshGroupListData(id, true);
|
||||||
|
return Result.ok(UnmodifiableListView([]));
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureResult<bool, ExecError> addUserToGroup(
|
FutureResult<bool, ExecError> addUserToGroup(
|
||||||
|
@ -291,37 +244,31 @@ class ConnectionsManager extends ChangeNotifier {
|
||||||
return result.execErrorCast();
|
return result.execErrorCast();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Connection, String> getById(String id) {
|
Result<Connection, ExecError> getById(String id) {
|
||||||
final result = _connectionsById[id];
|
return repo.getById(id).andThenSuccess((c) {
|
||||||
if (result == null) {
|
if (c.status == ConnectionStatus.unknown) {
|
||||||
return Result.error('$id not found');
|
_refreshConnection(c, true);
|
||||||
}
|
}
|
||||||
if (result.status == ConnectionStatus.unknown) {
|
return c;
|
||||||
_refreshConnection(result, true);
|
}).execErrorCast();
|
||||||
}
|
|
||||||
return Result.ok(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Connection, String> getByName(String name) {
|
Result<Connection, ExecError> getByName(String name) {
|
||||||
final result = _connectionsByName[name];
|
return repo.getByName(name).andThenSuccess((c) {
|
||||||
if (result == null) {
|
if (c.status == ConnectionStatus.unknown) {
|
||||||
Result.error('$name not found');
|
_refreshConnection(c, true);
|
||||||
}
|
}
|
||||||
if (result!.status == ConnectionStatus.unknown) {
|
return c;
|
||||||
_refreshConnection(result, true);
|
}).execErrorCast();
|
||||||
}
|
|
||||||
return Result.ok(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Connection, String> getByProfileUrl(Uri url) {
|
Result<Connection, ExecError> getByProfileUrl(Uri url) {
|
||||||
final result = _connectionsByProfileUrl[url];
|
return repo.getByProfileUrl(url.toString()).andThenSuccess((c) {
|
||||||
if (result == null) {
|
if (c.status == ConnectionStatus.unknown) {
|
||||||
Result.error('$url not found');
|
_refreshConnection(c, true);
|
||||||
}
|
}
|
||||||
if (result!.status == ConnectionStatus.unknown) {
|
return c;
|
||||||
_refreshConnection(result, true);
|
}).execErrorCast();
|
||||||
}
|
|
||||||
return Result.ok(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fullRefresh(Connection connection) async {
|
Future<void> fullRefresh(Connection connection) async {
|
||||||
|
@ -337,8 +284,8 @@ class ConnectionsManager extends ChangeNotifier {
|
||||||
.currentClient
|
.currentClient
|
||||||
.andThenAsync((client) => client.getMemberGroupsForConnection(id))
|
.andThenAsync((client) => client.getMemberGroupsForConnection(id))
|
||||||
.match(
|
.match(
|
||||||
onSuccess: (lists) {
|
onSuccess: (groups) {
|
||||||
_groupsForConnection[id] = lists;
|
repo.updateConnectionGroupData(id, groups);
|
||||||
if (withNotification) {
|
if (withNotification) {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
@ -376,8 +323,8 @@ class ConnectionsManager extends ChangeNotifier {
|
||||||
.match(
|
.match(
|
||||||
onSuccess: (groups) {
|
onSuccess: (groups) {
|
||||||
_logger.finest('Got updated groups:${groups.map((e) => e.name)}');
|
_logger.finest('Got updated groups:${groups.map((e) => e.name)}');
|
||||||
_myGroups.clear();
|
repo.clearGroups();
|
||||||
_myGroups.addAll(groups);
|
repo.addAllGroups(groups);
|
||||||
if (withNotification) {
|
if (withNotification) {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
|
@ -644,6 +644,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.1"
|
version: "2.4.1"
|
||||||
|
sqlite3:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: sqlite3
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.9.1"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -34,6 +34,7 @@ dependencies:
|
||||||
result_monad: ^2.0.2
|
result_monad: ^2.0.2
|
||||||
scrollable_positioned_list: ^0.3.5
|
scrollable_positioned_list: ^0.3.5
|
||||||
shared_preferences: ^2.0.15
|
shared_preferences: ^2.0.15
|
||||||
|
sqlite3: ^1.9.1
|
||||||
time_machine: ^0.9.17
|
time_machine: ^0.9.17
|
||||||
url_launcher: ^6.1.6
|
url_launcher: ^6.1.6
|
||||||
uuid: ^3.0.6
|
uuid: ^3.0.6
|
||||||
|
|
Loading…
Reference in a new issue