diff --git a/lib/ops/report-store-ops.js b/lib/ops/report-store-ops.js --- a/lib/ops/report-store-ops.js +++ b/lib/ops/report-store-ops.js @@ -21,6 +21,16 @@ | RemoveQueuedReportsOperation | RemoveAllQueuedReportsOperation; +export type ClientDBReplaceQueuedReportOperation = { + +type: 'replace_report', + +payload: { +id: string, +report: string }, +}; + +export type ClientDBReportStoreOperation = + | ClientDBReplaceQueuedReportOperation + | RemoveQueuedReportsOperation + | RemoveAllQueuedReportsOperation; + function processReportStoreOperations( queuedReports: $ReadOnlyArray, reportStoreOps: $ReadOnlyArray, 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 @@ -35,6 +35,9 @@ virtual jsi::Array getAllMessagesSync(jsi::Runtime &rt) override; virtual jsi::Value processDraftStoreOperations(jsi::Runtime &rt, jsi::Array operations) override; + virtual jsi::Value processReportStoreOperations( + jsi::Runtime &rt, + jsi::Array operations) override; virtual jsi::Value processMessageStoreOperations( jsi::Runtime &rt, jsi::Array operations) override; 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 @@ -6,6 +6,7 @@ #include "InternalModules/GlobalDBSingleton.h" #include "InternalModules/RustPromiseManager.h" #include "MessageStoreOperations.h" +#include "ReportStoreOperations.h" #include "TerminateApp.h" #include "ThreadStoreOperations.h" #include "lib.rs.h" @@ -792,6 +793,82 @@ }); } +const std::string REPLACE_REPORT_OPERATION = "replace_report"; +const std::string REMOVE_REPORTS_OPERATION = "remove_reports"; +const std::string REMOVE_ALL_REPORTS_OPERATION = "remove_all_reports"; + +std::vector> +createReportStoreOperations(jsi::Runtime &rt, const jsi::Array &operations) { + std::vector> reportStoreOps; + for (auto idx = 0; idx < operations.size(rt); idx++) { + auto op = operations.getValueAtIndex(rt, idx).asObject(rt); + auto op_type = op.getProperty(rt, "type").asString(rt).utf8(rt); + + if (op_type == REMOVE_ALL_REPORTS_OPERATION) { + reportStoreOps.push_back(std::make_unique()); + continue; + } + + auto payload_obj = op.getProperty(rt, "payload").asObject(rt); + if (op_type == REPLACE_REPORT_OPERATION) { + reportStoreOps.push_back( + std::make_unique(rt, payload_obj)); + } else if (op_type == REMOVE_REPORTS_OPERATION) { + reportStoreOps.push_back( + std::make_unique(rt, payload_obj)); + } else { + throw std::runtime_error{"unsupported operation: " + op_type}; + } + } + return reportStoreOps; +} + +jsi::Value CommCoreModule::processReportStoreOperations( + jsi::Runtime &rt, + jsi::Array operations) { + std::string createOperationsError; + std::shared_ptr>> + reportStoreOpsPtr; + try { + auto reportStoreOps = createReportStoreOperations(rt, operations); + reportStoreOpsPtr = std::make_shared< + std::vector>>( + std::move(reportStoreOps)); + } catch (std::runtime_error &e) { + createOperationsError = e.what(); + } + + return createPromiseAsJSIValue( + rt, [=](jsi::Runtime &innerRt, std::shared_ptr promise) { + taskType job = [=]() { + std::string error = createOperationsError; + + if (!error.size()) { + try { + DatabaseManager::getQueryExecutor().beginTransaction(); + for (const auto &operation : *reportStoreOpsPtr) { + operation->execute(); + } + DatabaseManager::getQueryExecutor().commitTransaction(); + } catch (std::system_error &e) { + error = e.what(); + DatabaseManager::getQueryExecutor().rollbackTransaction(); + } + } + + this->jsInvoker_->invokeAsync([=]() { + if (error.size()) { + promise->reject(error); + } else { + promise->resolve(jsi::Value::undefined()); + } + }); + }; + GlobalDBSingleton::instance.scheduleOrRunCancellable( + job, promise, this->jsInvoker_); + }); +} + void CommCoreModule::terminate(jsi::Runtime &rt) { TerminateApp::terminate(); } diff --git a/native/cpp/CommonCpp/NativeModules/ReportStoreOperations.h b/native/cpp/CommonCpp/NativeModules/ReportStoreOperations.h new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/NativeModules/ReportStoreOperations.h @@ -0,0 +1,57 @@ +#pragma once + +#include "../DatabaseManagers/entities/Media.h" +#include "../DatabaseManagers/entities/Report.h" +#include "DatabaseManager.h" +#include + +namespace comm { +class ReportStoreOperationBase { +public: + virtual void execute() = 0; + virtual ~ReportStoreOperationBase(){}; +}; + +class RemoveReportsOperation : public ReportStoreOperationBase { +public: + RemoveReportsOperation(jsi::Runtime &rt, const jsi::Object &payload) + : ids_to_remove{} { + auto payload_ids = payload.getProperty(rt, "ids").asObject(rt).asArray(rt); + for (size_t idx = 0; idx < payload_ids.size(rt); idx++) { + this->ids_to_remove.push_back( + payload_ids.getValueAtIndex(rt, idx).asString(rt).utf8(rt)); + } + } + + virtual void execute() override { + DatabaseManager::getQueryExecutor().removeReports(this->ids_to_remove); + } + +private: + std::vector ids_to_remove; +}; + +class ReplaceReportOperation : public ReportStoreOperationBase { +public: + ReplaceReportOperation(jsi::Runtime &rt, const jsi::Object &payload) { + auto report_id = payload.getProperty(rt, "id").asString(rt).utf8(rt); + auto report_data = payload.getProperty(rt, "report").asString(rt).utf8(rt); + + this->report = std::make_unique(Report{report_id, report_data}); + } + virtual void execute() override { + DatabaseManager::getQueryExecutor().replaceReport(std::move(*this->report)); + } + +private: + std::unique_ptr report; +}; + +class RemoveAllReportsOperation : public ReportStoreOperationBase { +public: + virtual void execute() override { + DatabaseManager::getQueryExecutor().removeAllReports(); + } +}; + +} // 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 @@ -46,6 +46,9 @@ static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processThreadStoreOperations(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->processThreadStoreOperations(rt, args[0].asObject(rt).asArray(rt)); } +static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processReportStoreOperations(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { + return static_cast(&turboModule)->processReportStoreOperations(rt, args[0].asObject(rt).asArray(rt)); +} static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processThreadStoreOperationsSync(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->processThreadStoreOperationsSync(rt, args[0].asObject(rt).asArray(rt)); return jsi::Value::undefined(); @@ -117,6 +120,7 @@ methodMap_["processMessageStoreOperationsSync"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processMessageStoreOperationsSync}; methodMap_["getAllThreadsSync"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getAllThreadsSync}; methodMap_["processThreadStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processThreadStoreOperations}; + methodMap_["processReportStoreOperations"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processReportStoreOperations}; methodMap_["processThreadStoreOperationsSync"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_processThreadStoreOperationsSync}; methodMap_["initializeCryptoAccount"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_initializeCryptoAccount}; methodMap_["getUserPublicKey"] = MethodMetadata {0, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getUserPublicKey}; 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 @@ -31,6 +31,7 @@ virtual void processMessageStoreOperationsSync(jsi::Runtime &rt, jsi::Array operations) = 0; virtual jsi::Array getAllThreadsSync(jsi::Runtime &rt) = 0; virtual jsi::Value processThreadStoreOperations(jsi::Runtime &rt, jsi::Array operations) = 0; + virtual jsi::Value processReportStoreOperations(jsi::Runtime &rt, jsi::Array operations) = 0; virtual void processThreadStoreOperationsSync(jsi::Runtime &rt, jsi::Array operations) = 0; virtual jsi::Value initializeCryptoAccount(jsi::Runtime &rt) = 0; virtual jsi::Value getUserPublicKey(jsi::Runtime &rt) = 0; @@ -158,6 +159,14 @@ return bridging::callFromJs( rt, &T::processThreadStoreOperations, jsInvoker_, instance_, std::move(operations)); } + jsi::Value processReportStoreOperations(jsi::Runtime &rt, jsi::Array operations) override { + static_assert( + bridging::getParameterCount(&T::processReportStoreOperations) == 2, + "Expected processReportStoreOperations(...) to have 2 parameters"); + + return bridging::callFromJs( + rt, &T::processReportStoreOperations, jsInvoker_, instance_, std::move(operations)); + } void processThreadStoreOperationsSync(jsi::Runtime &rt, jsi::Array operations) override { static_assert( bridging::getParameterCount(&T::processThreadStoreOperationsSync) == 2, 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 { ClientDBReportStoreOperation } from 'lib/ops/report-store-ops.js'; import type { ClientDBDraftStoreOperation } from 'lib/types/draft-types.js'; import type { ClientDBMessageInfo, @@ -49,6 +50,9 @@ +processThreadStoreOperations: ( operations: $ReadOnlyArray, ) => Promise; + +processReportStoreOperations: ( + operations: $ReadOnlyArray, + ) => Promise; +processThreadStoreOperationsSync: ( operations: $ReadOnlyArray, ) => void;