@shopify/react-native-skia 0.1.145 → 0.1.146
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cpp/api/JsiSkContourMeasure.h +4 -4
- package/cpp/api/JsiSkDataFactory.h +3 -3
- package/cpp/api/JsiSkFont.h +1 -1
- package/cpp/api/JsiSkPathFactory.h +1 -1
- package/cpp/api/JsiSkPictureFactory.h +1 -1
- package/cpp/api/JsiSkRuntimeEffect.h +6 -6
- package/cpp/api/JsiSkRuntimeEffectFactory.h +1 -1
- package/cpp/jsi/JsiSimpleValueWrapper.h +27 -27
- package/cpp/jsi/JsiValueWrapper.h +127 -0
- package/cpp/rnskia/RNSkDrawView.cpp +41 -17
- package/cpp/rnskia/RNSkDrawView.h +17 -19
- package/cpp/rnskia/RNSkJsiViewApi.h +180 -166
- package/cpp/rnskia/values/RNSkComputedValue.h +11 -11
- package/cpp/rnskia/values/RNSkReadonlyValue.h +19 -19
- package/cpp/rnskia/values/RNSkValue.h +13 -13
- package/cpp/utils/RNSkLog.h +4 -4
- package/lib/commonjs/renderer/HostConfig.js +17 -1
- package/lib/commonjs/renderer/HostConfig.js.map +1 -1
- package/lib/commonjs/views/SkiaView.js +11 -27
- package/lib/commonjs/views/SkiaView.js.map +1 -1
- package/lib/commonjs/views/types.js.map +1 -1
- package/lib/module/renderer/HostConfig.js +17 -1
- package/lib/module/renderer/HostConfig.js.map +1 -1
- package/lib/module/views/SkiaView.js +11 -26
- package/lib/module/views/SkiaView.js.map +1 -1
- package/lib/module/views/types.js.map +1 -1
- package/lib/typescript/src/views/SkiaView.d.ts +1 -11
- package/lib/typescript/src/views/types.d.ts +5 -5
- package/package.json +1 -1
- package/src/renderer/HostConfig.ts +11 -1
- package/src/views/SkiaView.tsx +17 -28
- package/src/views/types.ts +7 -6
| @@ -2,10 +2,12 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            #include <functional>
         | 
| 4 4 | 
             
            #include <memory>
         | 
| 5 | 
            +
            #include <mutex>
         | 
| 5 6 | 
             
            #include <string>
         | 
| 6 7 | 
             
            #include <vector>
         | 
| 7 8 |  | 
| 8 9 | 
             
            #include <JsiHostObject.h>
         | 
| 10 | 
            +
            #include <JsiValueWrapper.h>
         | 
| 9 11 | 
             
            #include <RNSkDrawView.h>
         | 
| 10 12 | 
             
            #include <RNSkPlatformContext.h>
         | 
| 11 13 | 
             
            #include <RNSkValue.h>
         | 
| @@ -14,96 +16,143 @@ | |
| 14 16 | 
             
            namespace RNSkia {
         | 
| 15 17 | 
             
            using namespace facebook;
         | 
| 16 18 |  | 
| 17 | 
            -
            using  | 
| 18 | 
            -
               | 
| 19 | 
            -
                drawCallback = nullptr;
         | 
| 19 | 
            +
            using RNSkViewInfo = struct RNSkViewInfo {
         | 
| 20 | 
            +
              RNSkViewInfo() {
         | 
| 20 21 | 
             
                view = nullptr;
         | 
| 21 22 | 
             
              }
         | 
| 22 | 
            -
              std::shared_ptr<FunctionWrapper> drawCallback;
         | 
| 23 23 | 
             
              std::shared_ptr<RNSkDrawView> view;
         | 
| 24 | 
            +
              std::unordered_map<std::string, JsiValueWrapper> props;
         | 
| 24 25 | 
             
            };
         | 
| 25 26 |  | 
| 26 | 
            -
            class RNSkJsiViewApi : public JsiHostObject {
         | 
| 27 | 
            +
            class RNSkJsiViewApi : public JsiHostObject, public std::enable_shared_from_this<RNSkJsiViewApi> {
         | 
| 27 28 | 
             
            public:
         | 
| 28 | 
            -
               | 
| 29 | 
            -
             | 
| 29 | 
            +
              /**
         | 
| 30 | 
            +
               Sets a custom property on a view given a view id. The property name/value will
         | 
| 31 | 
            +
               be stored in a map alongside the id of the view and propagated to the view when
         | 
| 32 | 
            +
               needed.
         | 
| 33 | 
            +
               */
         | 
| 34 | 
            +
              JSI_HOST_FUNCTION(setJsiProperty) {
         | 
| 35 | 
            +
                if (count != 3) {
         | 
| 30 36 | 
             
                  _platformContext->raiseError(
         | 
| 31 | 
            -
                      std::string(" | 
| 37 | 
            +
                      std::string("setJsiProperty: Expected 3 arguments, got " +
         | 
| 32 38 | 
             
                                  std::to_string(count) + "."));
         | 
| 33 39 | 
             
                  return jsi::Value::undefined();
         | 
| 34 40 | 
             
                }
         | 
| 35 41 |  | 
| 36 42 | 
             
                if (!arguments[0].isNumber()) {
         | 
| 37 43 | 
             
                  _platformContext->raiseError(
         | 
| 38 | 
            -
                      " | 
| 44 | 
            +
                      "setJsiProperty: First argument must be a number");
         | 
| 39 45 | 
             
                  return jsi::Value::undefined();
         | 
| 40 46 | 
             
                }
         | 
| 41 47 |  | 
| 42 | 
            -
                 | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
                    _platformContext->raiseError(
         | 
| 46 | 
            -
                        "setDrawCallback: Second argument must be a function");
         | 
| 47 | 
            -
                    return jsi::Value::undefined();
         | 
| 48 | 
            -
                  }
         | 
| 49 | 
            -
                  if (!arguments[1].asObject(runtime).isFunction(runtime)) {
         | 
| 50 | 
            -
                    _platformContext->raiseError(
         | 
| 51 | 
            -
                        "setDrawCallback: Second argument must be a function");
         | 
| 52 | 
            -
                    return jsi::Value::undefined();
         | 
| 53 | 
            -
                  }
         | 
| 54 | 
            -
                }
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                // find skia draw view
         | 
| 57 | 
            -
                int nativeId = arguments[0].asNumber();
         | 
| 48 | 
            +
                if (!arguments[1].isString()) {
         | 
| 49 | 
            +
                  _platformContext->raiseError(
         | 
| 50 | 
            +
                      "setJsiProperty: Second argument must be the name of the property to set.");
         | 
| 58 51 |  | 
| 59 | 
            -
             | 
| 60 | 
            -
                auto info = getEnsuredCallbackInfo(nativeId);
         | 
| 61 | 
            -
                if (arguments[1].isUndefined()) {
         | 
| 62 | 
            -
                  info->drawCallback = nullptr;
         | 
| 63 | 
            -
                } else {
         | 
| 64 | 
            -
                  info->drawCallback = std::make_shared<FunctionWrapper>(
         | 
| 65 | 
            -
                      arguments[1].asObject(runtime).asFunction(runtime));
         | 
| 52 | 
            +
                  return jsi::Value::undefined();
         | 
| 66 53 | 
             
                }
         | 
| 54 | 
            +
                auto nativeId = arguments[0].asNumber();
         | 
| 55 | 
            +
                auto info = getEnsuredViewInfo(nativeId);
         | 
| 67 56 |  | 
| 68 | 
            -
                 | 
| 69 | 
            -
                 | 
| 57 | 
            +
                std::lock_guard<std::mutex> lock(_mutex);
         | 
| 58 | 
            +
                info->props.emplace(arguments[1].asString(runtime).utf8(runtime), JsiValueWrapper(runtime, arguments[2]));
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                // Now let's see if we have a view that we can update
         | 
| 61 | 
            +
                if(info->view != nullptr) {
         | 
| 62 | 
            +
                  // Update view!
         | 
| 70 63 | 
             
                  info->view->setNativeId(nativeId);
         | 
| 71 | 
            -
                  info->view-> | 
| 64 | 
            +
                  info->view->setJsiProperties(info->props);
         | 
| 65 | 
            +
                  info->props.clear();
         | 
| 72 66 | 
             
                }
         | 
| 73 67 |  | 
| 74 68 | 
             
                return jsi::Value::undefined();
         | 
| 75 69 | 
             
              }
         | 
| 76 70 |  | 
| 77 | 
            -
               | 
| 78 | 
            -
             | 
| 71 | 
            +
              /**
         | 
| 72 | 
            +
               Calls a custom command / method on a view by the view id.
         | 
| 73 | 
            +
               */
         | 
| 74 | 
            +
              JSI_HOST_FUNCTION(callJsiMethod) {
         | 
| 75 | 
            +
                if (count < 2) {
         | 
| 79 76 | 
             
                  _platformContext->raiseError(
         | 
| 80 | 
            -
                      std::string(" | 
| 77 | 
            +
                      std::string("callCustomCommand: Expected at least 2 arguments, got " +
         | 
| 81 78 | 
             
                                  std::to_string(count) + "."));
         | 
| 79 | 
            +
             | 
| 82 80 | 
             
                  return jsi::Value::undefined();
         | 
| 83 81 | 
             
                }
         | 
| 84 82 |  | 
| 85 83 | 
             
                if (!arguments[0].isNumber()) {
         | 
| 86 84 | 
             
                  _platformContext->raiseError(
         | 
| 87 | 
            -
                      " | 
| 85 | 
            +
                      "callCustomCommand: First argument must be a number");
         | 
| 86 | 
            +
             | 
| 88 87 | 
             
                  return jsi::Value::undefined();
         | 
| 89 88 | 
             
                }
         | 
| 90 89 |  | 
| 91 | 
            -
                 | 
| 92 | 
            -
             | 
| 90 | 
            +
                if (!arguments[1].isString()) {
         | 
| 91 | 
            +
                  _platformContext->raiseError(
         | 
| 92 | 
            +
                      "callCustomCommand: Second argument must be the name of the action to call.");
         | 
| 93 93 |  | 
| 94 | 
            -
             | 
| 95 | 
            -
                if (info->view != nullptr) {
         | 
| 96 | 
            -
                  info->view->requestRedraw();
         | 
| 94 | 
            +
                  return jsi::Value::undefined();
         | 
| 97 95 | 
             
                }
         | 
| 98 | 
            -
             | 
| 96 | 
            +
             | 
| 97 | 
            +
                auto nativeId = arguments[0].asNumber();
         | 
| 98 | 
            +
                auto action = arguments[1].asString(runtime).utf8(runtime);
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                auto info = getEnsuredViewInfo(nativeId);
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                if(info->view == nullptr) {
         | 
| 103 | 
            +
                  throw jsi::JSError(runtime,
         | 
| 104 | 
            +
                      std::string("callCustomCommand: Could not call action " + action +
         | 
| 105 | 
            +
                                  " on view - view not ready.").c_str());
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  return jsi::Value::undefined();
         | 
| 108 | 
            +
                }
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                // Get arguments
         | 
| 111 | 
            +
                size_t paramsCount = count - 2;
         | 
| 112 | 
            +
                const jsi::Value* params = paramsCount > 0 ? &arguments[2] : nullptr;
         | 
| 113 | 
            +
                return info->view->callJsiMethod(runtime, action, params, paramsCount);
         | 
| 99 114 | 
             
              }
         | 
| 100 | 
            -
             | 
| 115 | 
            +
             | 
| 116 | 
            +
              JSI_HOST_FUNCTION(requestRedraw) {
         | 
| 117 | 
            +
                if (count < 2) {
         | 
| 118 | 
            +
                   _platformContext->raiseError(
         | 
| 119 | 
            +
                     std::string("requestRedraw: Expected 2 arguments, got " + std::to_string(count) + "."));
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                   return jsi::Value::undefined();
         | 
| 122 | 
            +
                 }
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                 if (!arguments[0].isNumber()) {
         | 
| 125 | 
            +
                   _platformContext->raiseError(
         | 
| 126 | 
            +
                       "requestRedraw: First argument must be a number");
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                   return jsi::Value::undefined();
         | 
| 129 | 
            +
                 }
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                 // find Skia View
         | 
| 132 | 
            +
                 int nativeId = arguments[0].asNumber();
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                 auto info = getEnsuredViewInfo(nativeId);
         | 
| 135 | 
            +
                 if (info->view != nullptr) {
         | 
| 136 | 
            +
                   info->view->requestRedraw();
         | 
| 137 | 
            +
                 }
         | 
| 138 | 
            +
                 return jsi::Value::undefined();
         | 
| 139 | 
            +
              }
         | 
| 140 | 
            +
             | 
| 101 141 | 
             
              JSI_HOST_FUNCTION(makeImageSnapshot) {
         | 
| 102 | 
            -
                
         | 
| 103 | 
            -
             | 
| 142 | 
            +
                if (count < 1) {
         | 
| 143 | 
            +
                  _platformContext->raiseError(std::string("makeImageSnapshot: Expected at least 1 argument, got " + std::to_string(count) + "."));
         | 
| 144 | 
            +
                  return jsi::Value::undefined();
         | 
| 145 | 
            +
                }
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                if (!arguments[0].isNumber()) {
         | 
| 148 | 
            +
                  _platformContext->raiseError("makeImageSnapshot: First argument must be a number");
         | 
| 149 | 
            +
                  return jsi::Value::undefined();
         | 
| 150 | 
            +
                }
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                // find Skia view
         | 
| 104 153 | 
             
                int nativeId = arguments[0].asNumber();
         | 
| 105 154 | 
             
                sk_sp<SkImage> image;
         | 
| 106 | 
            -
                auto info =  | 
| 155 | 
            +
                auto info = getEnsuredViewInfo(nativeId);
         | 
| 107 156 | 
             
                if (info->view != nullptr) {
         | 
| 108 157 | 
             
                  if(count > 1 && !arguments[1].isUndefined() && !arguments[1].isNull()) {
         | 
| 109 158 | 
             
                    auto rect = JsiSkRect::fromValue(runtime, arguments[1]);
         | 
| @@ -112,88 +161,66 @@ public: | |
| 112 161 | 
             
                    image = info->view->makeImageSnapshot(nullptr);
         | 
| 113 162 | 
             
                  }
         | 
| 114 163 | 
             
                  if(image == nullptr) {
         | 
| 115 | 
            -
                    jsi:: | 
| 164 | 
            +
                    throw jsi::JSError(runtime, "Could not create image from current surface.");
         | 
| 116 165 | 
             
                    return jsi::Value::undefined();
         | 
| 117 166 | 
             
                  }
         | 
| 118 167 | 
             
                  return jsi::Object::createFromHostObject(runtime, std::make_shared<JsiSkImage>(_platformContext, image));
         | 
| 119 168 | 
             
                }
         | 
| 120 | 
            -
                jsi:: | 
| 169 | 
            +
                throw jsi::JSError(runtime, "No Skia View currently available.");
         | 
| 121 170 | 
             
                return jsi::Value::undefined();
         | 
| 122 171 | 
             
              }
         | 
| 123 | 
            -
              
         | 
| 124 | 
            -
              JSI_HOST_FUNCTION(setDrawMode) {
         | 
| 125 | 
            -
                if (count != 2) {
         | 
| 126 | 
            -
                  _platformContext->raiseError(
         | 
| 127 | 
            -
                      std::string("setDrawMode: Expected 2 arguments, got " +
         | 
| 128 | 
            -
                                  std::to_string(count) + "."));
         | 
| 129 | 
            -
                  return jsi::Value::undefined();
         | 
| 130 | 
            -
                }
         | 
| 131 172 |  | 
| 132 | 
            -
                if (!arguments[0].isNumber()) {
         | 
| 133 | 
            -
                  _platformContext->raiseError(
         | 
| 134 | 
            -
                      "setDrawMode: First argument must be a number");
         | 
| 135 | 
            -
                  return jsi::Value::undefined();
         | 
| 136 | 
            -
                }
         | 
| 137 | 
            -
             | 
| 138 | 
            -
                // find skia draw view
         | 
| 139 | 
            -
                int nativeId = arguments[0].asNumber();
         | 
| 140 | 
            -
                auto info = getEnsuredCallbackInfo(nativeId);
         | 
| 141 | 
            -
                if (info->view != nullptr) {
         | 
| 142 | 
            -
                  auto nextMode = arguments[1].asString(runtime).utf8(runtime);
         | 
| 143 | 
            -
                  if(nextMode.compare("continuous") == 0) {
         | 
| 144 | 
            -
                    info->view->setDrawingMode(RNSkDrawingMode::Continuous);
         | 
| 145 | 
            -
                  } else {
         | 
| 146 | 
            -
                    info->view->setDrawingMode(RNSkDrawingMode::Default);
         | 
| 147 | 
            -
                  }
         | 
| 148 | 
            -
                }
         | 
| 149 | 
            -
                return jsi::Value::undefined();
         | 
| 150 | 
            -
              }
         | 
| 151 | 
            -
              
         | 
| 152 173 | 
             
              JSI_HOST_FUNCTION(registerValuesInView) {
         | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 157 | 
            -
                }
         | 
| 158 | 
            -
                
         | 
| 159 | 
            -
                // Get identifier of native SkiaView
         | 
| 160 | 
            -
                int nativeId = arguments[0].asNumber();
         | 
| 161 | 
            -
                
         | 
| 162 | 
            -
                // Get values that should be added as dependencies
         | 
| 163 | 
            -
                auto values = arguments[1].asObject(runtime).asArray(runtime);
         | 
| 164 | 
            -
                std::vector<std::function<void()>> unsubscribers;
         | 
| 165 | 
            -
                const std::size_t size = values.size(runtime);
         | 
| 166 | 
            -
                unsubscribers.reserve(size);
         | 
| 167 | 
            -
                for(size_t i=0; i<size; ++i) {
         | 
| 168 | 
            -
                  auto value = values.getValueAtIndex(runtime, i).asObject(runtime).asHostObject<RNSkReadonlyValue>(runtime);
         | 
| 169 | 
            -
                  
         | 
| 170 | 
            -
                  if(value != nullptr) {
         | 
| 171 | 
            -
                    // Add change listener
         | 
| 172 | 
            -
                    unsubscribers.push_back(value->addListener([this, nativeId](jsi::Runtime&){
         | 
| 173 | 
            -
                      requestRedrawView(nativeId);
         | 
| 174 | 
            -
                    }));
         | 
| 174 | 
            +
                  // Check params
         | 
| 175 | 
            +
                  if(!arguments[1].isObject() || !arguments[1].asObject(runtime).isArray(runtime)) {
         | 
| 176 | 
            +
                    throw jsi::JSError(runtime, "Expected array of Values as second parameter");
         | 
| 177 | 
            +
                    return jsi::Value::undefined();
         | 
| 175 178 | 
             
                  }
         | 
| 176 | 
            -
             | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
             | 
| 182 | 
            -
             | 
| 183 | 
            -
             | 
| 184 | 
            -
                   | 
| 185 | 
            -
                  for( | 
| 186 | 
            -
                     | 
| 179 | 
            +
             | 
| 180 | 
            +
                  // Get identifier of native SkiaView
         | 
| 181 | 
            +
                  int nativeId = arguments[0].asNumber();
         | 
| 182 | 
            +
             | 
| 183 | 
            +
                  // Get values that should be added as dependencies
         | 
| 184 | 
            +
                  auto values = arguments[1].asObject(runtime).asArray(runtime);
         | 
| 185 | 
            +
                  std::vector<std::function<void()>> unsubscribers;
         | 
| 186 | 
            +
                  const std::size_t size = values.size(runtime);
         | 
| 187 | 
            +
                  unsubscribers.reserve(size);
         | 
| 188 | 
            +
                  for(size_t i=0; i<size; ++i) {
         | 
| 189 | 
            +
                    auto value = values.getValueAtIndex(runtime, i).asObject(runtime).asHostObject<RNSkReadonlyValue>(runtime);
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                    if(value != nullptr) {
         | 
| 192 | 
            +
                      // Add change listener
         | 
| 193 | 
            +
                      unsubscribers.push_back(value->addListener([weakSelf = weak_from_this(), nativeId](jsi::Runtime&){
         | 
| 194 | 
            +
                        auto self = weakSelf.lock();
         | 
| 195 | 
            +
                        if(self) {
         | 
| 196 | 
            +
                          auto info = self->getEnsuredViewInfo(nativeId);
         | 
| 197 | 
            +
                          if(info->view != nullptr) {
         | 
| 198 | 
            +
                            info->view->requestRedraw();
         | 
| 199 | 
            +
                          }
         | 
| 200 | 
            +
                        }
         | 
| 201 | 
            +
                      }));
         | 
| 202 | 
            +
                    }
         | 
| 187 203 | 
             
                  }
         | 
| 188 | 
            -
             | 
| 189 | 
            -
             | 
| 190 | 
            -
             | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 194 | 
            -
             | 
| 195 | 
            -
             | 
| 196 | 
            -
             | 
| 204 | 
            +
             | 
| 205 | 
            +
                  // Return unsubscribe method that unsubscribes to all values
         | 
| 206 | 
            +
                  // that we subscribed to.
         | 
| 207 | 
            +
                  return jsi::Function::createFromHostFunction(runtime,
         | 
| 208 | 
            +
                                                               jsi::PropNameID::forUtf8(runtime, "unsubscribe"),
         | 
| 209 | 
            +
                                                               0,
         | 
| 210 | 
            +
                                                               JSI_HOST_FUNCTION_LAMBDA {
         | 
| 211 | 
            +
                    // decrease dependency count on the Skia View
         | 
| 212 | 
            +
                    for(auto &unsub : unsubscribers) {
         | 
| 213 | 
            +
                      unsub();
         | 
| 214 | 
            +
                    }
         | 
| 215 | 
            +
                    return jsi::Value::undefined();
         | 
| 216 | 
            +
                  });
         | 
| 217 | 
            +
                }
         | 
| 218 | 
            +
             | 
| 219 | 
            +
              JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkJsiViewApi, setJsiProperty),
         | 
| 220 | 
            +
                                   JSI_EXPORT_FUNC(RNSkJsiViewApi, callJsiMethod),
         | 
| 221 | 
            +
                                   JSI_EXPORT_FUNC(RNSkJsiViewApi, registerValuesInView),
         | 
| 222 | 
            +
                                   JSI_EXPORT_FUNC(RNSkJsiViewApi, requestRedraw),
         | 
| 223 | 
            +
                                   JSI_EXPORT_FUNC(RNSkJsiViewApi, makeImageSnapshot))
         | 
| 197 224 |  | 
| 198 225 | 
             
              /**
         | 
| 199 226 | 
             
               * Constructor
         | 
| @@ -203,7 +230,7 @@ public: | |
| 203 230 | 
             
                  : JsiHostObject(), _platformContext(platformContext) {}
         | 
| 204 231 |  | 
| 205 232 | 
             
              /**
         | 
| 206 | 
            -
               * Invalidates the  | 
| 233 | 
            +
               * Invalidates the Skia View Api object
         | 
| 207 234 | 
             
               */
         | 
| 208 235 | 
             
              void invalidate() {
         | 
| 209 236 | 
             
                unregisterAll();
         | 
| @@ -214,11 +241,12 @@ public: | |
| 214 241 | 
             
               */
         | 
| 215 242 | 
             
              void unregisterAll() {
         | 
| 216 243 | 
             
                // Unregister all views
         | 
| 217 | 
            -
                auto tempList =  | 
| 244 | 
            +
                auto tempList = _viewInfos;
         | 
| 218 245 | 
             
                for (const auto& info : tempList) {
         | 
| 219 246 | 
             
                  unregisterSkiaDrawView(info.first);
         | 
| 220 247 | 
             
                }
         | 
| 221 | 
            -
                 | 
| 248 | 
            +
                std::lock_guard<std::mutex> lock(_mutex);
         | 
| 249 | 
            +
                _viewInfos.clear();
         | 
| 222 250 | 
             
              }
         | 
| 223 251 |  | 
| 224 252 | 
             
              /**
         | 
| @@ -227,12 +255,12 @@ public: | |
| 227 255 | 
             
               * @param view View to register
         | 
| 228 256 | 
             
               */
         | 
| 229 257 | 
             
              void registerSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view) {
         | 
| 230 | 
            -
                auto info =  | 
| 258 | 
            +
                auto info = getEnsuredViewInfo(nativeId);
         | 
| 259 | 
            +
                std::lock_guard<std::mutex> lock(_mutex);
         | 
| 231 260 | 
             
                info->view = view;
         | 
| 232 | 
            -
                 | 
| 233 | 
            -
             | 
| 234 | 
            -
             | 
| 235 | 
            -
                }
         | 
| 261 | 
            +
                info->view->setNativeId(nativeId);
         | 
| 262 | 
            +
                info->view->setJsiProperties(info->props);
         | 
| 263 | 
            +
                info->props.clear();
         | 
| 236 264 | 
             
              }
         | 
| 237 265 |  | 
| 238 266 | 
             
              /**
         | 
| @@ -240,37 +268,34 @@ public: | |
| 240 268 | 
             
               * @param nativeId View id
         | 
| 241 269 | 
             
               */
         | 
| 242 270 | 
             
              void unregisterSkiaDrawView(size_t nativeId) {
         | 
| 243 | 
            -
                if ( | 
| 271 | 
            +
                if (_viewInfos.count(nativeId) == 0) {
         | 
| 244 272 | 
             
                  return;
         | 
| 245 273 | 
             
                }
         | 
| 246 | 
            -
                auto info =  | 
| 247 | 
            -
             | 
| 248 | 
            -
             | 
| 249 | 
            -
                }
         | 
| 274 | 
            +
                auto info = getEnsuredViewInfo(nativeId);
         | 
| 275 | 
            +
             | 
| 276 | 
            +
                std::lock_guard<std::mutex> lock(_mutex);
         | 
| 250 277 | 
             
                info->view = nullptr;
         | 
| 251 | 
            -
                 | 
| 252 | 
            -
                _callbackInfos.erase(nativeId);
         | 
| 278 | 
            +
                _viewInfos.erase(nativeId);
         | 
| 253 279 | 
             
              }
         | 
| 254 | 
            -
             | 
| 280 | 
            +
             | 
| 255 281 | 
             
              /**
         | 
| 256 282 | 
             
               Sets a skia draw view for the given id. This function can be used
         | 
| 257 283 | 
             
               to mark that an underlying SkiaView is not available (it could be
         | 
| 258 284 | 
             
               removed due to ex. a transition). The view can be set to a nullptr
         | 
| 259 | 
            -
               or a valid view, effectively toggling the view's availability. | 
| 260 | 
            -
               a valid view is set, the setDrawCallback method is called on the
         | 
| 261 | 
            -
               view (if a valid callback exists).
         | 
| 285 | 
            +
               or a valid view, effectively toggling the view's availability.
         | 
| 262 286 | 
             
               */
         | 
| 263 287 | 
             
              void setSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view) {
         | 
| 264 | 
            -
                if ( | 
| 288 | 
            +
                if (_viewInfos.find(nativeId) == _viewInfos.end()) {
         | 
| 265 289 | 
             
                  return;
         | 
| 266 290 | 
             
                }
         | 
| 267 | 
            -
                auto info =  | 
| 268 | 
            -
                 | 
| 291 | 
            +
                auto info = getEnsuredViewInfo(nativeId);
         | 
| 292 | 
            +
                std::lock_guard<std::mutex> lock(_mutex);
         | 
| 293 | 
            +
                if (view != nullptr) {
         | 
| 269 294 | 
             
                  info->view = view;
         | 
| 270 295 | 
             
                  info->view->setNativeId(nativeId);
         | 
| 271 | 
            -
                  info->view-> | 
| 272 | 
            -
             | 
| 273 | 
            -
             | 
| 296 | 
            +
                  info->view->setJsiProperties(info->props);
         | 
| 297 | 
            +
                  info->props.clear();
         | 
| 298 | 
            +
                } else if(view == nullptr) {
         | 
| 274 299 | 
             
                  info->view = view;
         | 
| 275 300 | 
             
                }
         | 
| 276 301 | 
             
              }
         | 
| @@ -281,28 +306,17 @@ private: | |
| 281 306 | 
             
               * @param nativeId View id
         | 
| 282 307 | 
             
               * @return The callback info object for the requested view
         | 
| 283 308 | 
             
               */
         | 
| 284 | 
            -
               | 
| 285 | 
            -
                if ( | 
| 286 | 
            -
                   | 
| 287 | 
            -
                   | 
| 288 | 
            -
             | 
| 289 | 
            -
                return &_callbackInfos.at(nativeId);
         | 
| 290 | 
            -
              }
         | 
| 291 | 
            -
              
         | 
| 292 | 
            -
              /**
         | 
| 293 | 
            -
                Send a redraw request to the view
         | 
| 294 | 
            -
               */
         | 
| 295 | 
            -
              void requestRedrawView(size_t nativeId) {
         | 
| 296 | 
            -
                auto info = getEnsuredCallbackInfo(nativeId);
         | 
| 297 | 
            -
                if(info->view != nullptr) {
         | 
| 298 | 
            -
                  info->view->requestRedraw();
         | 
| 309 | 
            +
              RNSkViewInfo *getEnsuredViewInfo(size_t nativeId) {
         | 
| 310 | 
            +
                if (_viewInfos.count(nativeId) == 0) {
         | 
| 311 | 
            +
                  RNSkViewInfo info;
         | 
| 312 | 
            +
                  std::lock_guard<std::mutex> lock(_mutex);
         | 
| 313 | 
            +
                  _viewInfos.emplace(nativeId, info);
         | 
| 299 314 | 
             
                }
         | 
| 315 | 
            +
                return &_viewInfos.at(nativeId);
         | 
| 300 316 | 
             
              }
         | 
| 301 | 
            -
             | 
| 302 | 
            -
               | 
| 303 | 
            -
              std::unordered_map<size_t, CallbackInfo> _callbackInfos;
         | 
| 304 | 
            -
              
         | 
| 305 | 
            -
              // Platform context
         | 
| 317 | 
            +
             | 
| 318 | 
            +
              std::unordered_map<size_t, RNSkViewInfo> _viewInfos;
         | 
| 306 319 | 
             
              std::shared_ptr<RNSkPlatformContext> _platformContext;
         | 
| 320 | 
            +
              std::mutex _mutex;
         | 
| 307 321 | 
             
            };
         | 
| 308 322 | 
             
            } // namespace RNSkia
         | 
| @@ -31,32 +31,32 @@ public: | |
| 31 31 | 
             
                // Verify input
         | 
| 32 32 | 
             
                if(!arguments[0].isObject() ||
         | 
| 33 33 | 
             
                   !arguments[0].asObject(runtime).isFunction(runtime)) {
         | 
| 34 | 
            -
                  jsi:: | 
| 34 | 
            +
                  throw jsi::JSError(runtime, "Expected callback function as first parameter");
         | 
| 35 35 | 
             
                }
         | 
| 36 | 
            -
             | 
| 36 | 
            +
             | 
| 37 37 | 
             
                if(!arguments[1].isObject() ||
         | 
| 38 38 | 
             
                   !arguments[1].asObject(runtime).isArray(runtime)) {
         | 
| 39 | 
            -
                  jsi:: | 
| 39 | 
            +
                  throw jsi::JSError(runtime, "Expected array of dependencies as second parameter");
         | 
| 40 40 | 
             
                }
         | 
| 41 | 
            -
             | 
| 41 | 
            +
             | 
| 42 42 | 
             
                // Get callback for calculating result
         | 
| 43 43 | 
             
                _callback = std::make_shared<jsi::Function>(arguments[0].asObject(runtime).asFunction(runtime));
         | 
| 44 44 | 
             
              }
         | 
| 45 | 
            -
             | 
| 45 | 
            +
             | 
| 46 46 | 
             
              void invalidate() override {
         | 
| 47 47 | 
             
                RNSkReadonlyValue::invalidate();
         | 
| 48 | 
            -
             | 
| 48 | 
            +
             | 
| 49 49 | 
             
                // Unregister listeners
         | 
| 50 50 | 
             
                for(const auto &unsubscribe: _unsubscribers) {
         | 
| 51 51 | 
             
                  unsubscribe();
         | 
| 52 52 | 
             
                }
         | 
| 53 53 | 
             
                _unsubscribers.clear();
         | 
| 54 54 | 
             
              }
         | 
| 55 | 
            -
             | 
| 55 | 
            +
             | 
| 56 56 | 
             
              void initializeDependencies(jsi::Runtime &runtime, const jsi::Value *arguments, size_t count) {
         | 
| 57 57 | 
             
                // Save dependencies
         | 
| 58 58 | 
             
                std::vector<std::shared_ptr<RNSkReadonlyValue>> dependencies;
         | 
| 59 | 
            -
             | 
| 59 | 
            +
             | 
| 60 60 | 
             
                // Ensure that all dependencies are Values
         | 
| 61 61 | 
             
                auto deps = arguments[1].asObject(runtime).asArray(runtime);
         | 
| 62 62 | 
             
                const std::size_t size = deps.size(runtime);
         | 
| @@ -73,7 +73,7 @@ public: | |
| 73 73 | 
             
                  }
         | 
| 74 74 | 
             
                  dependencies.push_back(value);
         | 
| 75 75 | 
             
                }
         | 
| 76 | 
            -
             | 
| 76 | 
            +
             | 
| 77 77 | 
             
                // register change handler on dependencies
         | 
| 78 78 | 
             
                _unsubscribers.reserve(_unsubscribers.size() + size);
         | 
| 79 79 | 
             
                for(const auto &dep: dependencies) {
         | 
| @@ -85,11 +85,11 @@ public: | |
| 85 85 | 
             
                    }
         | 
| 86 86 | 
             
                  }));
         | 
| 87 87 | 
             
                }
         | 
| 88 | 
            -
             | 
| 88 | 
            +
             | 
| 89 89 | 
             
                // Set initial value
         | 
| 90 90 | 
             
                dependencyUpdated(runtime);
         | 
| 91 91 | 
             
              }
         | 
| 92 | 
            -
             | 
| 92 | 
            +
             | 
| 93 93 | 
             
            private:
         | 
| 94 94 | 
             
              void dependencyUpdated(jsi::Runtime &runtime) {
         | 
| 95 95 | 
             
                // Calculate new value
         | 
| @@ -29,7 +29,7 @@ public: | |
| 29 29 | 
             
                  : JsiSkHostObject(platformContext),
         | 
| 30 30 | 
             
                  _valueHolder(std::make_unique<JsiSimpleValueWrapper>(*platformContext->getJsRuntime()))
         | 
| 31 31 | 
             
                  { }
         | 
| 32 | 
            -
             | 
| 32 | 
            +
             | 
| 33 33 | 
             
              virtual ~RNSkReadonlyValue() {
         | 
| 34 34 | 
             
                invalidate();
         | 
| 35 35 | 
             
              }
         | 
| @@ -37,21 +37,21 @@ public: | |
| 37 37 | 
             
              JSI_PROPERTY_GET(__typename__) {
         | 
| 38 38 | 
             
                return jsi::String::createFromUtf8(runtime, "RNSkValue");
         | 
| 39 39 | 
             
              }
         | 
| 40 | 
            -
             | 
| 40 | 
            +
             | 
| 41 41 | 
             
              JSI_PROPERTY_GET(current) {
         | 
| 42 42 | 
             
                return getCurrent(runtime);
         | 
| 43 43 | 
             
              }
         | 
| 44 | 
            -
             | 
| 44 | 
            +
             | 
| 45 45 | 
             
              JSI_EXPORT_PROPERTY_GETTERS(JSI_EXPORT_PROP_GET(RNSkReadonlyValue, __typename__),
         | 
| 46 46 | 
             
                                          JSI_EXPORT_PROP_GET(RNSkReadonlyValue, current))
         | 
| 47 | 
            -
             | 
| 47 | 
            +
             | 
| 48 48 | 
             
              JSI_HOST_FUNCTION(addListener) {
         | 
| 49 49 | 
             
                if(!arguments[0].isObject() || !arguments[0].asObject(runtime).isFunction(runtime)) {
         | 
| 50 | 
            -
                  jsi:: | 
| 50 | 
            +
                  throw jsi::JSError(runtime, "Expected function as first parameter.");
         | 
| 51 51 | 
             
                  return jsi::Value::undefined();
         | 
| 52 52 | 
             
                }
         | 
| 53 53 | 
             
                auto callback = std::make_shared<jsi::Function>(arguments[0].asObject(runtime).asFunction(runtime));
         | 
| 54 | 
            -
             | 
| 54 | 
            +
             | 
| 55 55 | 
             
                auto unsubscribe = addListener([weakSelf = weak_from_this(),
         | 
| 56 56 | 
             
                                                callback = std::move(callback)](jsi::Runtime& runtime){
         | 
| 57 57 | 
             
                  auto self = weakSelf.lock();
         | 
| @@ -60,7 +60,7 @@ public: | |
| 60 60 | 
             
                    callback->call(runtime, selfReadonlyValue->get_current(runtime));
         | 
| 61 61 | 
             
                  }
         | 
| 62 62 | 
             
                });
         | 
| 63 | 
            -
             | 
| 63 | 
            +
             | 
| 64 64 | 
             
                return jsi::Function::createFromHostFunction(runtime,
         | 
| 65 65 | 
             
                                                             jsi::PropNameID::forUtf8(runtime, "unsubscribe"),
         | 
| 66 66 | 
             
                                                             0,
         | 
| @@ -69,17 +69,17 @@ public: | |
| 69 69 | 
             
                  return jsi::Value::undefined();
         | 
| 70 70 | 
             
                });
         | 
| 71 71 | 
             
              }
         | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 72 | 
            +
             | 
| 73 | 
            +
             | 
| 74 | 
            +
             | 
| 75 75 | 
             
              JSI_HOST_FUNCTION(__invalidate) {
         | 
| 76 76 | 
             
                invalidate();
         | 
| 77 77 | 
             
                return jsi::Value::undefined();
         | 
| 78 78 | 
             
              }
         | 
| 79 | 
            -
             | 
| 79 | 
            +
             | 
| 80 80 | 
             
              JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(RNSkReadonlyValue, addListener),
         | 
| 81 81 | 
             
                                   JSI_EXPORT_FUNC(RNSkReadonlyValue, __invalidate))
         | 
| 82 | 
            -
             | 
| 82 | 
            +
             | 
| 83 83 | 
             
              /**
         | 
| 84 84 | 
             
              * Adds a callback that will be called whenever the value changes
         | 
| 85 85 | 
             
              * @param cb Callback
         | 
| @@ -96,7 +96,7 @@ public: | |
| 96 96 | 
             
                  }
         | 
| 97 97 | 
             
                };
         | 
| 98 98 | 
             
              }
         | 
| 99 | 
            -
             | 
| 99 | 
            +
             | 
| 100 100 | 
             
              /**
         | 
| 101 101 | 
             
                Updates the underlying value and notifies all listeners about the change.
         | 
| 102 102 | 
             
                Listeners are only notified if the value was actually changed for numeric, boolean and string
         | 
| @@ -111,7 +111,7 @@ public: | |
| 111 111 | 
             
                  notifyListeners(runtime);
         | 
| 112 112 | 
             
                }
         | 
| 113 113 | 
             
              }
         | 
| 114 | 
            -
             | 
| 114 | 
            +
             | 
| 115 115 | 
             
              /**
         | 
| 116 116 | 
             
               Override to implement invalidation logic for the value. In the base class this function
         | 
| 117 117 | 
             
               clears all subscribers.
         | 
| @@ -120,13 +120,13 @@ public: | |
| 120 120 | 
             
                std::lock_guard<std::mutex> lock(_mutex);
         | 
| 121 121 | 
             
                _listeners.clear();
         | 
| 122 122 | 
             
              }
         | 
| 123 | 
            -
             | 
| 123 | 
            +
             | 
| 124 124 | 
             
              jsi::Value getCurrent(jsi::Runtime &runtime) {
         | 
| 125 125 | 
             
                return _valueHolder->getCurrent(runtime);
         | 
| 126 126 | 
             
              }
         | 
| 127 | 
            -
             | 
| 127 | 
            +
             | 
| 128 128 | 
             
            protected:
         | 
| 129 | 
            -
             | 
| 129 | 
            +
             | 
| 130 130 | 
             
              /**
         | 
| 131 131 | 
             
                Notifies listeners about changes
         | 
| 132 132 | 
             
               @param runtime Current JS Runtime
         | 
| @@ -141,7 +141,7 @@ protected: | |
| 141 141 | 
             
                  listener.second(runtime);
         | 
| 142 142 | 
             
                }
         | 
| 143 143 | 
             
              }
         | 
| 144 | 
            -
             | 
| 144 | 
            +
             | 
| 145 145 | 
             
              /**
         | 
| 146 146 | 
             
               Removes a subscription listeners
         | 
| 147 147 | 
             
               @param listenerId identifier of listener to remove
         | 
| @@ -153,7 +153,7 @@ protected: | |
| 153 153 |  | 
| 154 154 | 
             
            private:
         | 
| 155 155 | 
             
              std::unique_ptr<JsiSimpleValueWrapper> _valueHolder;
         | 
| 156 | 
            -
             | 
| 156 | 
            +
             | 
| 157 157 | 
             
              long _listenerId = 0;
         | 
| 158 158 | 
             
              std::unordered_map<long, std::function<void(jsi::Runtime&)>> _listeners;
         | 
| 159 159 | 
             
              std::mutex _mutex;
         |