1*ab11e3c9SKudo Chien #include "MutableValue.h"
2*ab11e3c9SKudo Chien #include "RuntimeDecorator.h"
3*ab11e3c9SKudo Chien #include "RuntimeManager.h"
4*ab11e3c9SKudo Chien #include "ShareableValue.h"
5*ab11e3c9SKudo Chien #include "SharedParent.h"
6*ab11e3c9SKudo Chien
7*ab11e3c9SKudo Chien #include <string>
8*ab11e3c9SKudo Chien
9*ab11e3c9SKudo Chien namespace reanimated {
10*ab11e3c9SKudo Chien
setValue(jsi::Runtime & rt,const jsi::Value & newValue)11*ab11e3c9SKudo Chien void MutableValue::setValue(jsi::Runtime &rt, const jsi::Value &newValue) {
12*ab11e3c9SKudo Chien std::lock_guard<std::mutex> lock(readWriteMutex);
13*ab11e3c9SKudo Chien value = ShareableValue::adapt(rt, newValue, runtimeManager);
14*ab11e3c9SKudo Chien
15*ab11e3c9SKudo Chien std::shared_ptr<MutableValue> thiz = shared_from_this();
16*ab11e3c9SKudo Chien auto notifyListeners = [thiz]() {
17*ab11e3c9SKudo Chien for (auto listener : thiz->listeners) {
18*ab11e3c9SKudo Chien listener.second();
19*ab11e3c9SKudo Chien }
20*ab11e3c9SKudo Chien };
21*ab11e3c9SKudo Chien if (RuntimeDecorator::isUIRuntime(rt)) {
22*ab11e3c9SKudo Chien notifyListeners();
23*ab11e3c9SKudo Chien } else {
24*ab11e3c9SKudo Chien runtimeManager->scheduler->scheduleOnUI(
25*ab11e3c9SKudo Chien [notifyListeners] { notifyListeners(); });
26*ab11e3c9SKudo Chien }
27*ab11e3c9SKudo Chien }
28*ab11e3c9SKudo Chien
getValue(jsi::Runtime & rt)29*ab11e3c9SKudo Chien jsi::Value MutableValue::getValue(jsi::Runtime &rt) {
30*ab11e3c9SKudo Chien std::lock_guard<std::mutex> lock(readWriteMutex);
31*ab11e3c9SKudo Chien return value->getValue(rt);
32*ab11e3c9SKudo Chien }
33*ab11e3c9SKudo Chien
set(jsi::Runtime & rt,const jsi::PropNameID & name,const jsi::Value & newValue)34*ab11e3c9SKudo Chien void MutableValue::set(
35*ab11e3c9SKudo Chien jsi::Runtime &rt,
36*ab11e3c9SKudo Chien const jsi::PropNameID &name,
37*ab11e3c9SKudo Chien const jsi::Value &newValue) {
38*ab11e3c9SKudo Chien auto propName = name.utf8(rt);
39*ab11e3c9SKudo Chien if (!runtimeManager->valueSetter) {
40*ab11e3c9SKudo Chien throw jsi::JSError(
41*ab11e3c9SKudo Chien rt,
42*ab11e3c9SKudo Chien "Value-Setter is not yet configured! Make sure the core-functions are installed.");
43*ab11e3c9SKudo Chien }
44*ab11e3c9SKudo Chien
45*ab11e3c9SKudo Chien if (RuntimeDecorator::isUIRuntime(rt)) {
46*ab11e3c9SKudo Chien // UI thread
47*ab11e3c9SKudo Chien if (propName == "value") {
48*ab11e3c9SKudo Chien auto setterProxy = jsi::Object::createFromHostObject(
49*ab11e3c9SKudo Chien rt, std::make_shared<MutableValueSetterProxy>(shared_from_this()));
50*ab11e3c9SKudo Chien runtimeManager->valueSetter->getValue(rt)
51*ab11e3c9SKudo Chien .asObject(rt)
52*ab11e3c9SKudo Chien .asFunction(rt)
53*ab11e3c9SKudo Chien .callWithThis(rt, setterProxy, newValue);
54*ab11e3c9SKudo Chien } else if (propName == "_animation") {
55*ab11e3c9SKudo Chien // TODO: assert to allow animation to be set from UI only
56*ab11e3c9SKudo Chien if (animation.expired()) {
57*ab11e3c9SKudo Chien animation = getWeakRef(rt);
58*ab11e3c9SKudo Chien }
59*ab11e3c9SKudo Chien *animation.lock() = jsi::Value(rt, newValue);
60*ab11e3c9SKudo Chien } else if (propName == "_value") {
61*ab11e3c9SKudo Chien auto setter =
62*ab11e3c9SKudo Chien std::make_shared<MutableValueSetterProxy>(shared_from_this());
63*ab11e3c9SKudo Chien setter->set(rt, jsi::PropNameID::forAscii(rt, "_value"), newValue);
64*ab11e3c9SKudo Chien }
65*ab11e3c9SKudo Chien } else {
66*ab11e3c9SKudo Chien // React-JS Thread or another threaded Runtime.
67*ab11e3c9SKudo Chien if (propName == "value") {
68*ab11e3c9SKudo Chien auto shareable = ShareableValue::adapt(rt, newValue, runtimeManager);
69*ab11e3c9SKudo Chien runtimeManager->scheduler->scheduleOnUI([this, shareable] {
70*ab11e3c9SKudo Chien jsi::Runtime &rt = *this->runtimeManager->runtime.get();
71*ab11e3c9SKudo Chien auto setterProxy = jsi::Object::createFromHostObject(
72*ab11e3c9SKudo Chien rt, std::make_shared<MutableValueSetterProxy>(shared_from_this()));
73*ab11e3c9SKudo Chien jsi::Value newValue = shareable->getValue(rt);
74*ab11e3c9SKudo Chien runtimeManager->valueSetter->getValue(rt)
75*ab11e3c9SKudo Chien .asObject(rt)
76*ab11e3c9SKudo Chien .asFunction(rt)
77*ab11e3c9SKudo Chien .callWithThis(rt, setterProxy, newValue);
78*ab11e3c9SKudo Chien });
79*ab11e3c9SKudo Chien }
80*ab11e3c9SKudo Chien }
81*ab11e3c9SKudo Chien }
82*ab11e3c9SKudo Chien
get(jsi::Runtime & rt,const jsi::PropNameID & name)83*ab11e3c9SKudo Chien jsi::Value MutableValue::get(jsi::Runtime &rt, const jsi::PropNameID &name) {
84*ab11e3c9SKudo Chien auto propName = name.utf8(rt);
85*ab11e3c9SKudo Chien
86*ab11e3c9SKudo Chien if (propName == "value") {
87*ab11e3c9SKudo Chien return getValue(rt);
88*ab11e3c9SKudo Chien }
89*ab11e3c9SKudo Chien
90*ab11e3c9SKudo Chien if (RuntimeDecorator::isUIRuntime(rt)) {
91*ab11e3c9SKudo Chien // _value and _animation should be accessed from UI only
92*ab11e3c9SKudo Chien if (propName == "_value") {
93*ab11e3c9SKudo Chien return getValue(rt);
94*ab11e3c9SKudo Chien } else if (propName == "_animation") {
95*ab11e3c9SKudo Chien // TODO: assert to allow animation to be read from UI only
96*ab11e3c9SKudo Chien if (animation.expired()) {
97*ab11e3c9SKudo Chien animation = getWeakRef(rt);
98*ab11e3c9SKudo Chien }
99*ab11e3c9SKudo Chien return jsi::Value(rt, *(animation.lock()));
100*ab11e3c9SKudo Chien }
101*ab11e3c9SKudo Chien }
102*ab11e3c9SKudo Chien
103*ab11e3c9SKudo Chien return jsi::Value::undefined();
104*ab11e3c9SKudo Chien }
105*ab11e3c9SKudo Chien
getPropertyNames(jsi::Runtime & rt)106*ab11e3c9SKudo Chien std::vector<jsi::PropNameID> MutableValue::getPropertyNames(jsi::Runtime &rt) {
107*ab11e3c9SKudo Chien std::vector<jsi::PropNameID> result;
108*ab11e3c9SKudo Chien result.push_back(jsi::PropNameID::forUtf8(rt, std::string("value")));
109*ab11e3c9SKudo Chien return result;
110*ab11e3c9SKudo Chien }
111*ab11e3c9SKudo Chien
MutableValue(jsi::Runtime & rt,const jsi::Value & initial,RuntimeManager * runtimeManager,std::shared_ptr<Scheduler> s)112*ab11e3c9SKudo Chien MutableValue::MutableValue(
113*ab11e3c9SKudo Chien jsi::Runtime &rt,
114*ab11e3c9SKudo Chien const jsi::Value &initial,
115*ab11e3c9SKudo Chien RuntimeManager *runtimeManager,
116*ab11e3c9SKudo Chien std::shared_ptr<Scheduler> s)
117*ab11e3c9SKudo Chien : StoreUser(s, *runtimeManager),
118*ab11e3c9SKudo Chien runtimeManager(runtimeManager),
119*ab11e3c9SKudo Chien value(ShareableValue::adapt(rt, initial, runtimeManager)) {}
120*ab11e3c9SKudo Chien
addListener(unsigned long id,std::function<void ()> listener)121*ab11e3c9SKudo Chien unsigned long int MutableValue::addListener(
122*ab11e3c9SKudo Chien unsigned long id,
123*ab11e3c9SKudo Chien std::function<void()> listener) {
124*ab11e3c9SKudo Chien listeners[id] = listener;
125*ab11e3c9SKudo Chien return id;
126*ab11e3c9SKudo Chien }
127*ab11e3c9SKudo Chien
removeListener(unsigned long listenerId)128*ab11e3c9SKudo Chien void MutableValue::removeListener(unsigned long listenerId) {
129*ab11e3c9SKudo Chien if (listeners.count(listenerId) > 0) {
130*ab11e3c9SKudo Chien listeners.erase(listenerId);
131*ab11e3c9SKudo Chien }
132*ab11e3c9SKudo Chien }
133*ab11e3c9SKudo Chien
134*ab11e3c9SKudo Chien } // namespace reanimated
135