Initial Connections Repo implementation with memory version ported into MemoryConnectionsRepo

codemagic-setup
Hank Grabowski 2023-01-16 15:31:17 -06:00
rodzic 3d6ab6998f
commit b1e4dbf4cc
6 zmienionych plików z 275 dodań i 107 usunięć

Wyświetl plik

@ -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();
}
}

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -5,6 +5,8 @@ import 'package:multi_trigger_autocomplete/multi_trigger_autocomplete.dart';
import 'package:provider/provider.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 'models/TimelineIdentifiers.dart';
import 'routes.dart';
@ -44,6 +46,7 @@ void main() async {
await service.initialize();
return service;
});
getIt.registerSingleton<IConnectionsRepo>(MemoryConnectionsRepo());
getIt.registerLazySingleton<ConnectionsManager>(() => ConnectionsManager());
getIt.registerLazySingleton<HashtagService>(() => HashtagService());
getIt.registerSingleton(galleryService);

Wyświetl plik

@ -1,9 +1,11 @@
import 'dart:collection';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:result_monad/result_monad.dart';
import '../data/interfaces/connections_repo_intf.dart';
import '../globals.dart';
import '../models/connection.dart';
import '../models/exec_error.dart';
@ -12,75 +14,26 @@ import 'auth_service.dart';
class ConnectionsManager extends ChangeNotifier {
static final _logger = Logger('$ConnectionsManager');
final _connectionsById = <String, Connection>{};
final _connectionsByName = <String, Connection>{};
final _connectionsByProfileUrl = <Uri, Connection>{};
final _groupsForConnection = <String, List<GroupData>>{};
final _myGroups = <GroupData>{};
final _myContacts = <Connection>[];
var _myContactsInitialized = false;
late final IConnectionsRepo repo;
int get length => _connectionsById.length;
void clearCaches() {
_connectionsById.clear();
_connectionsByName.clear();
_connectionsByProfileUrl.clear();
_groupsForConnection.clear();
_myGroups.clear();
_myContacts.clear();
ConnectionsManager() {
repo = getIt<IConnectionsRepo>();
}
bool addConnection(Connection connection) {
if (_connectionsById.containsKey(connection.id)) {
return false;
}
return updateConnection(connection);
return repo.addConnection(connection);
}
List<Connection> getKnownUsersByName(String name) {
return _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);
}).toList();
return repo.getKnownUsersByName(name);
}
bool updateConnection(Connection connection) {
_connectionsById[connection.id] = 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;
return repo.updateConnection(connection);
}
bool addAllConnections(Iterable<Connection> newConnections) {
bool result = true;
for (final connection in newConnections) {
result &= addConnection(connection);
}
return result;
return repo.addAllConnections(newConnections);
}
Future<void> acceptFollowRequest(Connection connection) async {
@ -178,13 +131,8 @@ class ConnectionsManager extends ChangeNotifier {
);
}
List<Connection> getMyContacts() {
if (!_myContactsInitialized) {
updateAllContacts();
_myContactsInitialized = true;
}
return _myContacts.toList(growable: false);
UnmodifiableListView<Connection> getMyContacts() {
return repo.getMyContacts();
}
Future<void> updateAllContacts() async {
@ -234,29 +182,34 @@ class ConnectionsManager extends ChangeNotifier {
});
}
_myContacts.clear();
_myContacts.addAll(results.values);
addAllConnections(results.values);
_myContacts.sort((c1, c2) => c1.name.compareTo(c2.name));
_logger.finest('# Contacts:${_myContacts.length}');
final myContacts = repo.getMyContacts().toList();
myContacts.sort((c1, c2) => c1.name.compareTo(c2.name));
_logger.finest('# Contacts:${myContacts.length}');
notifyListeners();
}
List<GroupData> getMyGroups() {
if (_myGroups.isNotEmpty) {
return _myGroups.toList(growable: false);
UnmodifiableListView<GroupData> getMyGroups() {
final myGroups = repo.getMyGroups();
if (myGroups.isEmpty) {
_updateMyGroups(true);
}
_updateMyGroups(true);
return [];
return myGroups;
}
Result<List<GroupData>, ExecError> getGroupsForUser(String id) {
if (!_groupsForConnection.containsKey(id)) {
_refreshGroupListData(id, true);
return Result.ok([]);
final result = repo.getGroupsForUser(id);
if (result.isSuccess) {
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(
@ -291,37 +244,31 @@ class ConnectionsManager extends ChangeNotifier {
return result.execErrorCast();
}
Result<Connection, String> getById(String id) {
final result = _connectionsById[id];
if (result == null) {
return Result.error('$id not found');
}
if (result.status == ConnectionStatus.unknown) {
_refreshConnection(result, true);
}
return Result.ok(result);
Result<Connection, ExecError> getById(String id) {
return repo.getById(id).andThenSuccess((c) {
if (c.status == ConnectionStatus.unknown) {
_refreshConnection(c, true);
}
return c;
}).execErrorCast();
}
Result<Connection, String> getByName(String name) {
final result = _connectionsByName[name];
if (result == null) {
Result.error('$name not found');
}
if (result!.status == ConnectionStatus.unknown) {
_refreshConnection(result, true);
}
return Result.ok(result);
Result<Connection, ExecError> getByName(String name) {
return repo.getByName(name).andThenSuccess((c) {
if (c.status == ConnectionStatus.unknown) {
_refreshConnection(c, true);
}
return c;
}).execErrorCast();
}
Result<Connection, String> getByProfileUrl(Uri url) {
final result = _connectionsByProfileUrl[url];
if (result == null) {
Result.error('$url not found');
}
if (result!.status == ConnectionStatus.unknown) {
_refreshConnection(result, true);
}
return Result.ok(result);
Result<Connection, ExecError> getByProfileUrl(Uri url) {
return repo.getByProfileUrl(url.toString()).andThenSuccess((c) {
if (c.status == ConnectionStatus.unknown) {
_refreshConnection(c, true);
}
return c;
}).execErrorCast();
}
Future<void> fullRefresh(Connection connection) async {
@ -337,8 +284,8 @@ class ConnectionsManager extends ChangeNotifier {
.currentClient
.andThenAsync((client) => client.getMemberGroupsForConnection(id))
.match(
onSuccess: (lists) {
_groupsForConnection[id] = lists;
onSuccess: (groups) {
repo.updateConnectionGroupData(id, groups);
if (withNotification) {
notifyListeners();
}
@ -376,8 +323,8 @@ class ConnectionsManager extends ChangeNotifier {
.match(
onSuccess: (groups) {
_logger.finest('Got updated groups:${groups.map((e) => e.name)}');
_myGroups.clear();
_myGroups.addAll(groups);
repo.clearGroups();
repo.addAllGroups(groups);
if (withNotification) {
notifyListeners();
}

Wyświetl plik

@ -644,6 +644,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.4.1"
sqlite3:
dependency: "direct main"
description:
name: sqlite3
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.1"
stack_trace:
dependency: transitive
description:

Wyświetl plik

@ -34,6 +34,7 @@ dependencies:
result_monad: ^2.0.2
scrollable_positioned_list: ^0.3.5
shared_preferences: ^2.0.15
sqlite3: ^1.9.1
time_machine: ^0.9.17
url_launcher: ^6.1.6
uuid: ^3.0.6