Skip to content

Commit d0a227f

Browse files
author
pioner921227
committed
updated ios
1 parent a090ef5 commit d0a227f

File tree

10 files changed

+255
-212
lines changed

10 files changed

+255
-212
lines changed

SyncTasks.podspec

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ Pod::Spec.new do |s|
1515

1616
s.source_files = "ios/**/*.{h,m,mm}", "cpp/**/*.{hpp,cpp,c,h}"
1717

18-
s.dependency 'curl'
19-
2018
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
2119
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
2220
if respond_to?(:install_modules_dependencies, true)

cpp/JSTask.cpp

Lines changed: 93 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -7,170 +7,138 @@
77

88
#include "JSTask.hpp"
99

10+
#include "TaskScheduler.hpp"
1011
#include "constants.hpp"
12+
#include "helpers/FetchService.hpp"
1113
#include "helpers/fetch.h"
1214
#include "helpers/helpers.h"
13-
#include "TaskScheduler.hpp"
14-
1515

1616
using namespace facebook;
1717

1818
constexpr std::hash<std::string> hasher;
1919

2020
jsi::Function createJSTaskCreator(
21-
jsi::Runtime &rt,
22-
std::shared_ptr<react::CallInvoker> callInvoker) {
23-
jsi::Function createTask = jsi::Function::createFromHostFunction(
24-
rt, jsi::PropNameID::forAscii(rt, CREATE_TASK_KEY), 1,
25-
[callInvoker = std::move(callInvoker)](
26-
jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args,
27-
size_t count) {
28-
jsi::Object taskJS(rt);
29-
30-
if (!args[0].isObject()) {
31-
throw jsi::JSError(
32-
rt,
33-
"[SyncTasksManager]: createTask -> argument must be an object");
34-
}
35-
36-
jsi::Object props = args[0].asObject(rt);
37-
38-
jsi::Object config = props.getPropertyAsObject(rt, CONFIG_KEY);
39-
40-
int interval = config.getProperty(rt, INTERVAL_KEY).asNumber();
41-
std::string url = config.getProperty(rt, URL_KEY).asString(rt).utf8(rt);
42-
43-
if (!checkJSType<jsi::Function>(rt,
44-
props.getProperty(rt, ON_DATA_KEY))) {
45-
throw jsi::JSError(rt,
46-
"[SyncTasksManager]: onData must be a function");
47-
}
21+
jsi::Runtime& rt,
22+
std::shared_ptr<react::CallInvoker> callInvoker) {
23+
jsi::Function createTask = jsi::Function::createFromHostFunction(
24+
rt, jsi::PropNameID::forAscii(rt, CREATE_TASK_KEY), 1,
25+
[callInvoker = std::move(callInvoker)](
26+
jsi::Runtime& rt, const jsi::Value& thisVal, const jsi::Value* args,
27+
size_t count) {
28+
jsi::Object taskJS(rt);
4829

49-
auto onData = std::make_shared<jsi::Function>(
50-
props.getPropertyAsFunction(rt, ON_DATA_KEY));
30+
if (!args[0].isObject()) {
31+
throw jsi::JSError(
32+
rt,
33+
"[SyncTasksManager]: createTask -> argument must be an object");
34+
}
5135

52-
jsi::Value onErrorValue = props.getProperty(rt, ON_ERROR_KEY);
36+
jsi::Object props = args[0].asObject(rt);
5337

54-
std::shared_ptr<jsi::Function> onError;
38+
jsi::Object config = props.getPropertyAsObject(rt, CONFIG_KEY);
5539

56-
if (checkJSType<jsi::Function>(rt, onErrorValue)) {
57-
onError = std::make_shared<jsi::Function>(
58-
props.getPropertyAsFunction(rt, ON_ERROR_KEY));
59-
}
40+
int interval = config.getProperty(rt, INTERVAL_KEY).asNumber();
41+
std::string url = config.getProperty(rt, URL_KEY).asString(rt).utf8(rt);
6042

61-
std::unordered_map<std::string, std::string> c_headers;
43+
if (!checkJSType<jsi::Function>(rt,
44+
props.getProperty(rt, ON_DATA_KEY))) {
45+
throw jsi::JSError(rt,
46+
"[SyncTasksManager]: onData must be a function");
47+
}
6248

63-
jsi::Value headers = config.getProperty(rt, HEADERS_KEY);
49+
auto onData = std::make_shared<jsi::Function>(
50+
props.getPropertyAsFunction(rt, ON_DATA_KEY));
6451

65-
if (headers.isObject()) {
66-
jsi::Object h = headers.asObject(rt);
52+
jsi::Value onErrorValue = props.getProperty(rt, ON_ERROR_KEY);
6753

68-
jsi::Array names = h.getPropertyNames(rt);
54+
std::shared_ptr<jsi::Function> onError;
6955

70-
for (int i = 0; i < names.size(rt); ++i) {
71-
jsi::Value keyValue = names.getValueAtIndex(rt, i);
56+
auto fetcher = rt.global().getNativeState<FetchService>(rt);
7257

73-
if (!keyValue.isString()) [[unlikely]] {
74-
throw jsi::JSError(
75-
rt,
76-
"[SyncTasksManager] Invalid Header, key must be a string");
77-
}
58+
if (checkJSType<jsi::Function>(rt, onErrorValue)) {
59+
onError = std::make_shared<jsi::Function>(
60+
props.getPropertyAsFunction(rt, ON_ERROR_KEY));
61+
}
7862

79-
jsi::String key = keyValue.asString(rt);
63+
FetchHeaders headers = getFetchHeadersFromJSObject(rt, config);
8064

81-
jsi::Value valValue = h.getProperty(rt, key);
65+
auto task = std::make_shared<Task>(
66+
url, interval,
67+
[url, fetcher, callInvoker, onData, onError, &rt,
68+
h = std::move(headers)](Task& self) mutable {
69+
auto response = fetcher->fetch(url, std::move(h));
8270

83-
if (!valValue.isString()) [[unlikely]] {
84-
throw jsi::JSError(
85-
rt,
86-
"[SyncTasksManager] Invalid Header, value must be a string");
87-
}
71+
if (std::holds_alternative<FetchBody>(response)) {
72+
auto& data = std::get<FetchBody>(response);
8873

89-
jsi::String value = valValue.asString(rt);
74+
size_t bodyHash = hasher(data.body);
9075

91-
c_headers[key.utf8(rt)] = value.utf8(rt);
92-
}
76+
if (self.hasSameBodyHash(bodyHash)) {
77+
return;
9378
}
9479

95-
auto task = std::make_shared<Task>(
96-
url, interval,
97-
[url, callInvoker, onData, onError, &rt,
98-
h = std::move(c_headers)](Task &self) mutable {
99-
auto response = fetch(url.c_str(), std::move(h));
100-
101-
if (std::holds_alternative<FetchResult>(response)) {
102-
auto &data = std::get<FetchResult>(response);
103-
104-
size_t bodyHash = hasher(data.body);
105-
106-
if (self.hasSameBodyHash(bodyHash)) {
107-
return;
108-
}
109-
110-
self.setLastBodyHash(bodyHash);
80+
self.setLastBodyHash(bodyHash);
11181

112-
callInvoker->invokeAsync(
113-
[&rt, onData, body = std::move(data.body)] {
114-
onData->call(rt, jsi::String::createFromUtf8(rt, body));
115-
});
82+
callInvoker->invokeAsync(
83+
[&rt, onData, body = std::move(data.body)] {
84+
onData->call(rt, jsi::String::createFromUtf8(rt, body));
85+
});
11686

117-
} else {
118-
auto &err = std::get<FetchError>(response);
87+
} else {
88+
auto& err = std::get<FetchError>(response);
11989

120-
callInvoker->invokeAsync([onError, &rt, err = std::move(err)] {
121-
if (onError) {
122-
jsi::Object error(rt);
90+
callInvoker->invokeAsync([onError, &rt, err = std::move(err)] {
91+
if (onError) {
92+
jsi::Object error(rt);
12393

124-
error.setProperty(
125-
rt, "error",
126-
jsi::String::createFromUtf8(rt, err.message));
127-
error.setProperty(
128-
rt, "body", jsi::String::createFromUtf8(rt, err.body));
129-
error.setProperty(rt, "status_code",
130-
jsi::Value((int) err.httpCode));
94+
error.setProperty(
95+
rt, "error",
96+
jsi::String::createFromUtf8(rt, err.message));
97+
error.setProperty(
98+
rt, "body", jsi::String::createFromUtf8(rt, err.body));
99+
error.setProperty(rt, "status_code",
100+
jsi::Value((int)err.httpCode));
131101

132-
onError->call(rt, error);
133-
}
134-
});
135-
}
136-
});
102+
onError->call(rt, error);
103+
}
104+
});
105+
}
106+
});
137107

138-
jsi::Function stopTask = jsi::Function::createFromHostFunction(
139-
rt, jsi::PropNameID::forAscii(rt, "stopTask"), 1,
140-
[task](jsi::Runtime &rt, const jsi::Value &thisVal,
141-
const jsi::Value *args, size_t count) {
142-
task->stop();
108+
jsi::Function stopTask = jsi::Function::createFromHostFunction(
109+
rt, jsi::PropNameID::forAscii(rt, "stopTask"), 1,
110+
[task](jsi::Runtime& rt, const jsi::Value& thisVal,
111+
const jsi::Value* args, size_t count) {
112+
task->stop();
143113

144-
return jsi::Value(true);
145-
});
114+
return jsi::Value(true);
115+
});
146116

147-
jsi::Function startTask = jsi::Function::createFromHostFunction(
148-
rt, jsi::PropNameID::forAscii(rt, "startTask"), 1,
149-
[task](jsi::Runtime &rt, const jsi::Value &thisVal,
150-
const jsi::Value *args, size_t count) {
151-
task->start();
117+
jsi::Function startTask = jsi::Function::createFromHostFunction(
118+
rt, jsi::PropNameID::forAscii(rt, "startTask"), 1,
119+
[task](jsi::Runtime& rt, const jsi::Value& thisVal,
120+
const jsi::Value* args, size_t count) {
121+
task->start();
152122

153-
return jsi::Value(true);
154-
});
123+
return jsi::Value(true);
124+
});
155125

156-
jsi::Function isRunning = jsi::Function::createFromHostFunction(
157-
rt, jsi::PropNameID::forAscii(rt, "isRunning"), 1,
158-
[task](jsi::Runtime &rt, const jsi::Value &thisVal,
159-
const jsi::Value *args,
160-
size_t count) {
161-
return jsi::Value(!task->isStopped());
162-
});
126+
jsi::Function isRunning = jsi::Function::createFromHostFunction(
127+
rt, jsi::PropNameID::forAscii(rt, "isRunning"), 1,
128+
[task](jsi::Runtime& rt, const jsi::Value& thisVal,
129+
const jsi::Value* args,
130+
size_t count) { return jsi::Value(!task->isStopped()); });
163131

164-
taskJS.setNativeState(rt, task);
132+
taskJS.setNativeState(rt, task);
165133

166-
taskJS.setProperty(rt, "stop", std::move(stopTask));
167-
taskJS.setProperty(rt, "start", std::move(startTask));
168-
taskJS.setProperty(rt, "isRunning", std::move(isRunning));
134+
taskJS.setProperty(rt, "stop", std::move(stopTask));
135+
taskJS.setProperty(rt, "start", std::move(startTask));
136+
taskJS.setProperty(rt, "isRunning", std::move(isRunning));
169137

170-
taskJS.setExternalMemoryPressure(rt, sizeof(Task));
138+
taskJS.setExternalMemoryPressure(rt, sizeof(Task));
171139

172-
return taskJS;
173-
});
140+
return taskJS;
141+
});
174142

175-
return createTask;
143+
return createTask;
176144
}

cpp/constants.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ constexpr const char* ADD_TASKS_KEY = "addTasks";
2121
constexpr const char* START_ALL_KEY = "startAll";
2222
constexpr const char* STOP_ALL_KEY = "stopAll";
2323

24+
constexpr const char* FETCHER_KEY = "__fetcher";
25+
2426
constexpr int THREADS_COUNT = 4;

cpp/helpers/FetchService.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// FetchService.cpp
3+
// SyncTasks
4+
//
5+
// Created by Oleksandr Shumihin on 13/4/25.
6+
//
7+
8+
#include "FetchService.hpp"
9+
#include "jsi/jsi.h"
10+
11+
12+
FetchService::FetchService(FetchFn fn):fetcher_(std::move(fn)) {};
13+
14+
FetchService::~FetchService(){};
15+
16+
FetchResponse FetchService::fetch(std::string url, FetchHeaders&& headers) {
17+
return fetcher_(std::move(url), std::move(headers));
18+
};

cpp/helpers/FetchService.hpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//
2+
// FetchService.hpp
3+
// SyncTasks
4+
//
5+
// Created by Oleksandr Shumihin on 13/4/25.
6+
//
7+
8+
#ifndef FetchService_hpp
9+
#define FetchService_hpp
10+
11+
#include "jsi/jsi.h"
12+
13+
struct FetchBody {
14+
std::string body;
15+
FetchBody() = default;
16+
FetchBody(std::string b) : body(std::move(b)) {}
17+
};
18+
19+
struct FetchError {
20+
std::string message;
21+
std::string body;
22+
long httpCode = 0;
23+
24+
FetchError() = default;
25+
26+
FetchError(std::string msg, std::string b, long code)
27+
: message(std::move(msg)), body(std::move(b)), httpCode(code) {}
28+
};
29+
30+
31+
using FetchResponse = std::variant<FetchBody,FetchError>;
32+
33+
using FetchHeaders = std::unordered_map<std::string, std::string>;
34+
35+
using FetchFn = std::function<FetchResponse(std::string&& url, FetchHeaders&& headers)>;
36+
37+
using namespace facebook;
38+
39+
class FetchService:public jsi::NativeState {
40+
public:
41+
FetchService(FetchFn fn);
42+
43+
~FetchService();
44+
45+
FetchResponse fetch(std::string url, FetchHeaders&& headers);
46+
47+
private:
48+
FetchFn fetcher_;
49+
};
50+
51+
#endif /* FetchService_hpp */

0 commit comments

Comments
 (0)