diff --git a/native/cpp/CommonCpp/NativeModules/CMakeLists.txt b/native/cpp/CommonCpp/NativeModules/CMakeLists.txt --- a/native/cpp/CommonCpp/NativeModules/CMakeLists.txt +++ b/native/cpp/CommonCpp/NativeModules/CMakeLists.txt @@ -19,6 +19,7 @@ "DraftStoreOperations.h" "UserStoreOperations.h" "KeyserverStoreOperations.h" + "CommunityStoreOperations.h" ) set(NATIVE_SRCS @@ -81,6 +82,7 @@ ${_data_stores_path}/ReportStore.h ${_data_stores_path}/UserStore.h ${_data_stores_path}/KeyserverStore.h + ${_data_stores_path}/CommunityStore.h ) set(DATA_STORES_SRCS ${_data_stores_path}/DraftStore.cpp @@ -89,6 +91,7 @@ ${_data_stores_path}/ReportStore.cpp ${_data_stores_path}/UserStore.cpp ${_data_stores_path}/KeyserverStore.cpp + ${_data_stores_path}/CommunityStore.cpp ) set(_backup_op_path ./PersistentStorageUtilities/BackupOperationsUtilities) diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h --- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h +++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h @@ -4,6 +4,7 @@ #include "../Tools/CommSecureStore.h" #include "../Tools/WorkerThread.h" #include "../_generated/commJSI.h" +#include "PersistentStorageUtilities/DataStores/CommunityStore.h" #include "PersistentStorageUtilities/DataStores/DraftStore.h" #include "PersistentStorageUtilities/DataStores/KeyserverStore.h" #include "PersistentStorageUtilities/DataStores/MessageStore.h" @@ -32,6 +33,7 @@ ReportStore reportStore; UserStore userStore; KeyserverStore keyserverStore; + CommunityStore communityStore; void persistCryptoModule(); @@ -69,6 +71,9 @@ virtual jsi::Value processKeyserverStoreOperations( jsi::Runtime &rt, jsi::Array operations) override; + virtual jsi::Value processCommunityStoreOperations( + jsi::Runtime &rt, + jsi::Array operations) override; virtual jsi::Value initializeCryptoAccount(jsi::Runtime &rt) override; virtual jsi::Value getUserPublicKey(jsi::Runtime &rt) override; virtual jsi::Value diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp --- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp +++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp @@ -311,6 +311,12 @@ return this->keyserverStore.processStoreOperations(rt, std::move(operations)); } +jsi::Value CommCoreModule::processCommunityStoreOperations( + jsi::Runtime &rt, + jsi::Array operations) { + return this->communityStore.processStoreOperations(rt, std::move(operations)); +} + void CommCoreModule::terminate(jsi::Runtime &rt) { TerminateApp::terminate(); } @@ -1051,7 +1057,8 @@ messageStore(jsInvoker), reportStore(jsInvoker), userStore(jsInvoker), - keyserverStore(jsInvoker) { + keyserverStore(jsInvoker), + communityStore(jsInvoker) { GlobalDBSingleton::instance.enableMultithreading(); } diff --git a/native/cpp/CommonCpp/NativeModules/CommunityStoreOperations.h b/native/cpp/CommonCpp/NativeModules/CommunityStoreOperations.h new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/CommunityStoreOperations.h @@ -0,0 +1,48 @@ +#pragma once + +#include "../DatabaseManagers/entities/CommunityInfo.h" +#include "DatabaseManager.h" +#include + +namespace comm { +class CommunityStoreOperationBase { +public: + virtual void execute() = 0; + virtual ~CommunityStoreOperationBase(){}; +}; + +class RemoveCommunitiesOperation : public CommunityStoreOperationBase { +public: + RemoveCommunitiesOperation(std::vector ids) : ids{ids} { + } + + virtual void execute() override { + DatabaseManager::getQueryExecutor().removeCommunities(this->ids); + } + +private: + std::vector ids; +}; + +class ReplaceCommunityOperation : public CommunityStoreOperationBase { +public: + ReplaceCommunityOperation(CommunityInfo &&community) + : community{std::move(community)} { + } + + virtual void execute() override { + DatabaseManager::getQueryExecutor().replaceCommunity(this->community); + } + +private: + CommunityInfo community; +}; + +class RemoveAllCommunitiesOperation : public CommunityStoreOperationBase { +public: + virtual void execute() override { + DatabaseManager::getQueryExecutor().removeAllCommunities(); + } +}; + +} // namespace comm diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/CommunityStore.h b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/CommunityStore.h new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/CommunityStore.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../../../DatabaseManagers/entities/CommunityInfo.h" +#include "BaseDataStore.h" +#include "CommunityStoreOperations.h" + +#include + +namespace comm { + +class CommunityStore + : public BaseDataStore { +private: + static OperationType REMOVE_OPERATION; + static OperationType REMOVE_ALL_OPERATION; + static OperationType REPLACE_OPERATION; + +public: + CommunityStore(std::shared_ptr jsInvoker); + + std::vector> createOperations( + jsi::Runtime &rt, + const jsi::Array &operations) const override; + + jsi::Array parseDBDataStore( + jsi::Runtime &rt, + std::shared_ptr> dataVectorPtr) const override; +}; + +} // namespace comm diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/CommunityStore.cpp b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/CommunityStore.cpp new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/DataStores/CommunityStore.cpp @@ -0,0 +1,67 @@ +#include "CommunityStore.h" + +#include +#include + +namespace comm { + +OperationType CommunityStore::REMOVE_OPERATION = "remove_communities"; +OperationType CommunityStore::REMOVE_ALL_OPERATION = "remove_all_communities"; +OperationType CommunityStore::REPLACE_OPERATION = "replace_community"; + +CommunityStore::CommunityStore( + std::shared_ptr jsInvoker) + : BaseDataStore(jsInvoker) { +} + +jsi::Array CommunityStore::parseDBDataStore( + jsi::Runtime &rt, + std::shared_ptr> communitiesVectorPtr) const { + jsi::Array jsiCommunities = jsi::Array(rt, 0); + return jsiCommunities; +} + +std::vector> +CommunityStore::createOperations(jsi::Runtime &rt, const jsi::Array &operations) + const { + std::vector> communityStoreOps; + + for (size_t idx = 0; idx < operations.size(rt); idx++) { + jsi::Object op = operations.getValueAtIndex(rt, idx).asObject(rt); + std::string opType = op.getProperty(rt, "type").asString(rt).utf8(rt); + + if (opType == REMOVE_OPERATION) { + std::vector communityIDsToRemove; + jsi::Object payloadObj = op.getProperty(rt, "payload").asObject(rt); + jsi::Array communityIDs = + payloadObj.getProperty(rt, "ids").asObject(rt).asArray(rt); + for (int communityIdx = 0; communityIdx < communityIDs.size(rt); + communityIdx++) { + communityIDsToRemove.push_back( + communityIDs.getValueAtIndex(rt, communityIdx) + .asString(rt) + .utf8(rt)); + } + communityStoreOps.push_back(std::make_unique( + std::move(communityIDsToRemove))); + } else if (opType == REMOVE_ALL_OPERATION) { + communityStoreOps.push_back( + std::make_unique()); + } else if (opType == REPLACE_OPERATION) { + jsi::Object payloadObj = op.getProperty(rt, "payload").asObject(rt); + std::string id = payloadObj.getProperty(rt, "id").asString(rt).utf8(rt); + std::string community_info = + payloadObj.getProperty(rt, "communityInfo").asString(rt).utf8(rt); + + CommunityInfo community{id, community_info}; + + communityStoreOps.push_back( + std::make_unique(std::move(community))); + } else { + throw std::runtime_error("unsupported operation: " + opType); + } + }; + return communityStoreOps; +} + +} // namespace comm diff --git a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp --- a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp +++ b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp @@ -63,6 +63,9 @@ static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processKeyserverStoreOperations(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->processKeyserverStoreOperations(rt, args[0].asObject(rt).asArray(rt)); } +static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processCommunityStoreOperations(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->processCommunityStoreOperations(rt, args[0].asObject(rt).asArray(rt)); +} static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeCryptoAccount(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->initializeCryptoAccount(rt); } @@ -179,6 +182,7 @@ methodMap_["processThreadStoreOperationsSync"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processThreadStoreOperationsSync}; methodMap_["processUserStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processUserStoreOperations}; methodMap_["processKeyserverStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processKeyserverStoreOperations}; + methodMap_["processCommunityStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processCommunityStoreOperations}; methodMap_["initializeCryptoAccount"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeCryptoAccount}; methodMap_["getUserPublicKey"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getUserPublicKey}; methodMap_["getOneTimeKeys"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getOneTimeKeys}; diff --git a/native/cpp/CommonCpp/_generated/commJSI.h b/native/cpp/CommonCpp/_generated/commJSI.h --- a/native/cpp/CommonCpp/_generated/commJSI.h +++ b/native/cpp/CommonCpp/_generated/commJSI.h @@ -36,6 +36,7 @@ virtual void processThreadStoreOperationsSync(jsi::Runtime &rt, jsi::Array operations) = 0; virtual jsi::Value processUserStoreOperations(jsi::Runtime &rt, jsi::Array operations) = 0; virtual jsi::Value processKeyserverStoreOperations(jsi::Runtime &rt, jsi::Array operations) = 0; + virtual jsi::Value processCommunityStoreOperations(jsi::Runtime &rt, jsi::Array operations) = 0; virtual jsi::Value initializeCryptoAccount(jsi::Runtime &rt) = 0; virtual jsi::Value getUserPublicKey(jsi::Runtime &rt) = 0; virtual jsi::Value getOneTimeKeys(jsi::Runtime &rt, double oneTimeKeysAmount) = 0; @@ -216,6 +217,14 @@ return bridging::callFromJs( rt, &T::processKeyserverStoreOperations, jsInvoker_, instance_, std::move(operations)); } + jsi::Value processCommunityStoreOperations(jsi::Runtime &rt, jsi::Array operations) override { + static_assert( + bridging::getParameterCount(&T::processCommunityStoreOperations) == 2, + "Expected processCommunityStoreOperations(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::processCommunityStoreOperations, jsInvoker_, instance_, std::move(operations)); + } jsi::Value initializeCryptoAccount(jsi::Runtime &rt) override { static_assert( bridging::getParameterCount(&T::initializeCryptoAccount) == 1, diff --git a/native/ios/Comm.xcodeproj/project.pbxproj b/native/ios/Comm.xcodeproj/project.pbxproj --- a/native/ios/Comm.xcodeproj/project.pbxproj +++ b/native/ios/Comm.xcodeproj/project.pbxproj @@ -55,6 +55,7 @@ 8EF7756B2A7433630046A385 /* ThreadStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8EF775692A7433630046A385 /* ThreadStore.cpp */; }; 8EF7756E2A7513F40046A385 /* MessageStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8EF7756D2A7513F40046A385 /* MessageStore.cpp */; }; 8EF775712A751B780046A385 /* ReportStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8EF7756F2A751B780046A385 /* ReportStore.cpp */; }; + B3B02EBF2B8538980020D118 /* CommunityStore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B3B02EBD2B8536560020D118 /* CommunityStore.cpp */; }; B71AFF1F265EDD8600B22352 /* IBMPlexSans-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B71AFF1E265EDD8600B22352 /* IBMPlexSans-Medium.ttf */; }; CB01F0C22B67EF5A0089E1F9 /* SQLiteDataConverters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB01F0C12B67EF470089E1F9 /* SQLiteDataConverters.cpp */; }; CB01F0C42B67F3A10089E1F9 /* SQLiteStatementWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CB01F0C32B67F3970089E1F9 /* SQLiteStatementWrapper.cpp */; }; @@ -235,6 +236,9 @@ 8EF775702A751B780046A385 /* ReportStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ReportStore.h; path = PersistentStorageUtilities/DataStores/ReportStore.h; sourceTree = ""; }; 913E5A7BDECB327E3DE11053 /* Pods-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.release.xcconfig"; sourceTree = ""; }; 994BEBDD4E4959F69CEA0BC3 /* libPods-Comm.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Comm.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + B3B02EBC2B8534C00020D118 /* CommunityStore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommunityStore.h; path = PersistentStorageUtilities/DataStores/CommunityStore.h; sourceTree = ""; }; + B3B02EBD2B8536560020D118 /* CommunityStore.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CommunityStore.cpp; path = PersistentStorageUtilities/DataStores/CommunityStore.cpp; sourceTree = ""; }; + B3B02EBE2B8538860020D118 /* CommunityStoreOperations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommunityStoreOperations.h; sourceTree = ""; }; B7055C6B26E477CF00BE0548 /* MessageStoreOperations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MessageStoreOperations.h; sourceTree = ""; }; B70FBC1226B047050040F480 /* Message.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Message.h; sourceTree = ""; }; B71AFF1E265EDD8600B22352 /* IBMPlexSans-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "IBMPlexSans-Medium.ttf"; path = "Resources/IBMPlexSans-Medium.ttf"; sourceTree = ""; }; @@ -453,6 +457,7 @@ 71BE843A2636A944002849D2 /* NativeModules */ = { isa = PBXGroup; children = ( + B3B02EBE2B8538860020D118 /* CommunityStoreOperations.h */, 8E2CC2562B5C999A000C94D6 /* KeyserverStoreOperations.h */, CBA784382B28AC4300E9F419 /* CommServicesAuthMetadataEmitter.h */, 8E3994562B039A9300D5E950 /* UserStoreOperations.h */, @@ -631,6 +636,8 @@ children = ( 8E2CC2582B5C99B0000C94D6 /* KeyserverStore.cpp */, 8E2CC2572B5C99B0000C94D6 /* KeyserverStore.h */, + B3B02EBD2B8536560020D118 /* CommunityStore.cpp */, + B3B02EBC2B8534C00020D118 /* CommunityStore.h */, 8E3994532B039A7C00D5E950 /* UserStore.cpp */, 8E3994542B039A7C00D5E950 /* UserStore.h */, 8EF7756F2A751B780046A385 /* ReportStore.cpp */, @@ -1120,6 +1127,7 @@ 7F0C6E31291C4468002AA2D9 /* ExpoModulesProvider.swift in Sources */, 8EF775682A74032C0046A385 /* CommRustModule.cpp in Sources */, 8E43C32C291E5B4A009378F5 /* TerminateApp.mm in Sources */, + B3B02EBF2B8538980020D118 /* CommunityStore.cpp in Sources */, 8BC9568529FC49B00060AE4A /* JSIRust.cpp in Sources */, 8EA59BD92A73DAB000EB4F53 /* rustJSI-generated.cpp in Sources */, CB38B48628771CDD00171182 /* TemporaryMessageStorage.mm in Sources */, diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js --- a/native/schema/CommCoreModuleSchema.js +++ b/native/schema/CommCoreModuleSchema.js @@ -5,6 +5,7 @@ import { TurboModuleRegistry } from 'react-native'; import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport.js'; +import type { ClientDBCommunityStoreOperation } from 'lib/ops/community-store-ops.js'; import type { ClientDBKeyserverStoreOperation } from 'lib/ops/keyserver-store-ops'; import type { ClientDBMessageStoreOperation } from 'lib/ops/message-store-ops.js'; import type { ClientDBReportStoreOperation } from 'lib/ops/report-store-ops.js'; @@ -70,6 +71,9 @@ +processKeyserverStoreOperations: ( operations: $ReadOnlyArray, ) => Promise; + +processCommunityStoreOperations: ( + operations: $ReadOnlyArray, + ) => Promise; +initializeCryptoAccount: () => Promise; +getUserPublicKey: () => Promise; +getOneTimeKeys: (oneTimeKeysAmount: number) => Promise;