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