react-native-unistyles 3.0.0-alpha.22 → 3.0.0-alpha.24

Sign up to get free protection for your applications and to get access to all the features.
@@ -149,3 +149,29 @@ core::DependencyMap core::UnistylesRegistry::buildDependencyMap(jsi::Runtime& rt
149
149
 
150
150
  return dependencyMap;
151
151
  }
152
+
153
+ std::vector<std::shared_ptr<core::StyleSheet>> core::UnistylesRegistry::getStyleSheetsToRefresh(jsi::Runtime& rt, bool themeDidChange, bool runtimeDidChange) {
154
+ std::vector<std::shared_ptr<core::StyleSheet>> stylesheetsToRefresh{};
155
+
156
+ if (!themeDidChange && !runtimeDidChange) {
157
+ return stylesheetsToRefresh;
158
+ }
159
+
160
+ auto& styleSheets = this->_styleSheetRegistry[&rt];
161
+
162
+ std::for_each(styleSheets.begin(), styleSheets.end(), [&](std::pair<int, std::shared_ptr<core::StyleSheet>> pair){
163
+ auto& [_, styleSheet] = pair;
164
+
165
+ if (styleSheet->type == StyleSheetType::ThemableWithMiniRuntime && runtimeDidChange) {
166
+ stylesheetsToRefresh.emplace_back(styleSheet);
167
+
168
+ return;
169
+ }
170
+
171
+ if (styleSheet->type == StyleSheetType::Themable && themeDidChange) {
172
+ stylesheetsToRefresh.emplace_back(styleSheet);
173
+ }
174
+ });
175
+
176
+ return stylesheetsToRefresh;
177
+ }
@@ -36,6 +36,7 @@ struct UnistylesRegistry: public StyleSheetRegistry {
36
36
 
37
37
  UnistylesState& getState(jsi::Runtime& rt);
38
38
  void createState(jsi::Runtime& rt);
39
+ std::vector<std::shared_ptr<core::StyleSheet>> getStyleSheetsToRefresh(jsi::Runtime& rt, bool themeDidChange, bool runtimeDidChange);
39
40
  void linkShadowNodeWithUnistyle(jsi::Runtime& rt, const ShadowNodeFamily*, std::vector<core::Unistyle::Shared>& unistyles, Variants& variants, std::vector<folly::dynamic>&);
40
41
  void unlinkShadowNodeWithUnistyles(jsi::Runtime& rt, const ShadowNodeFamily*);
41
42
  std::shared_ptr<core::StyleSheet> addStyleSheet(jsi::Runtime& rt, int tag, core::StyleSheetType type, jsi::Object&& rawValue);
@@ -223,18 +223,24 @@ void HybridStyleSheet::onPlatformDependenciesChange(std::vector<UnistyleDependen
223
223
 
224
224
  // check if color scheme changed and then if Unistyles state depend on it (adaptive themes)
225
225
  auto colorSchemeIt = std::find(dependencies.begin(), dependencies.end(), UnistyleDependency::COLORSCHEME);
226
-
227
- if (colorSchemeIt != dependencies.end()) {
226
+ auto hasNewColorScheme = colorSchemeIt != dependencies.end();
227
+
228
+ // in a later step, we will rebuild only Unistyles with mounted StyleSheets
229
+ // however, user may have StyleSheets with components that haven't mounted yet
230
+ // we need to rebuild all dependent StyleSheets as well
231
+ auto dependentStyleSheets = registry.getStyleSheetsToRefresh(rt, hasNewColorScheme, dependencies.size() > 1);
232
+
233
+ if (hasNewColorScheme) {
228
234
  this->_unistylesRuntime->includeDependenciesForColorSchemeChange(dependencies);
229
235
  }
230
-
236
+
231
237
  auto dependencyMap = registry.buildDependencyMap(rt, dependencies);
232
238
 
233
239
  if (dependencyMap.size() == 0) {
234
240
  return;
235
241
  }
236
242
 
237
- parser.rebuildUnistylesInDependencyMap(rt, dependencyMap);
243
+ parser.rebuildUnistylesInDependencyMap(rt, dependencyMap, dependentStyleSheets);
238
244
 
239
245
  // this is required, otherwise shadow tree will ignore Unistyles commit
240
246
  registry.trafficController.setHasUnistylesCommit(true);
@@ -99,9 +99,16 @@ void parser::Parser::rebuildUnistylesWithVariants(jsi::Runtime& rt, std::shared_
99
99
  }
100
100
 
101
101
  // rebuild all unistyles that are affected by platform event
102
- void parser::Parser::rebuildUnistylesInDependencyMap(jsi::Runtime& rt, DependencyMap& dependencyMap) {
102
+ void parser::Parser::rebuildUnistylesInDependencyMap(jsi::Runtime& rt, DependencyMap& dependencyMap, std::vector<std::shared_ptr<core::StyleSheet>> styleSheets) {
103
103
  std::unordered_map<std::shared_ptr<StyleSheet>, jsi::Value> parsedStyleSheets{};
104
+ std::unordered_map<std::shared_ptr<core::Unistyle>, bool> parsedUnistyles{};
104
105
 
106
+ // parse all stylesheets that depends on changes
107
+ for (auto styleSheet : styleSheets) {
108
+ parsedStyleSheets.emplace(styleSheet, this->unwrapStyleSheet(rt, styleSheet));
109
+ }
110
+
111
+ // then parse all visible Unistyles
105
112
  for (auto& [shadowNode, unistyles] : dependencyMap) {
106
113
  auto styleSheet = unistyles.begin()->get()->unistyle->parent;
107
114
 
@@ -116,6 +123,10 @@ void parser::Parser::rebuildUnistylesInDependencyMap(jsi::Runtime& rt, Dependenc
116
123
  // for RN styles or inline styles, compute styles only once
117
124
  if (unistyle->styleKey == helpers::EXOTIC_STYLE_KEY.c_str() && !unistyleData->parsedStyle.has_value()) {
118
125
  unistyleData->parsedStyle = jsi::Value(rt, unistyle->rawValue).asObject(rt);
126
+
127
+ if (!parsedUnistyles.contains(unistyle)) {
128
+ parsedUnistyles.emplace(unistyle, true);
129
+ }
119
130
 
120
131
  continue;
121
132
  }
@@ -128,6 +139,21 @@ void parser::Parser::rebuildUnistylesInDependencyMap(jsi::Runtime& rt, Dependenc
128
139
  unistyle->rawValue = parsedStyleSheets[styleSheet].asObject(rt).getProperty(rt, unistyle->styleKey.c_str()).asObject(rt);
129
140
  this->rebuildUnistyle(rt, styleSheet, unistyle, unistyleData->variants, unistyleData->dynamicFunctionMetadata);
130
141
  unistyleData->parsedStyle = jsi::Value(rt, unistyle->parsedStyle.value()).asObject(rt);
142
+
143
+ if (!parsedUnistyles.contains(unistyle)) {
144
+ parsedUnistyles.emplace(unistyle, true);
145
+ }
146
+ }
147
+ }
148
+
149
+ // parse whatever left in StyleSheets
150
+ for (auto styleSheet : styleSheets) {
151
+ for (auto& [_, unistyle] : styleSheet->unistyles) {
152
+ if (!parsedUnistyles.contains(unistyle)) {
153
+ parsedUnistyles.emplace(unistyle, true);
154
+ unistyle->rawValue = parsedStyleSheets[styleSheet].asObject(rt).getProperty(rt, unistyle->styleKey.c_str()).asObject(rt);
155
+ this->rebuildUnistyle(rt, styleSheet, unistyle, {}, std::nullopt);
156
+ }
131
157
  }
132
158
  }
133
159
  }
@@ -24,7 +24,7 @@ struct Parser {
24
24
  void buildUnistyles(jsi::Runtime& rt, std::shared_ptr<StyleSheet> styleSheet);
25
25
  void parseUnistyles(jsi::Runtime& rt, std::shared_ptr<StyleSheet> styleSheet);
26
26
  void rebuildUnistylesWithVariants(jsi::Runtime& rt, std::shared_ptr<StyleSheet> styleSheet, Variants& variants);
27
- void rebuildUnistylesInDependencyMap(jsi::Runtime& rt, core::DependencyMap& dependencyMap);
27
+ void rebuildUnistylesInDependencyMap(jsi::Runtime& rt, core::DependencyMap& dependencyMap, std::vector<std::shared_ptr<core::StyleSheet>> styleSheets);
28
28
  shadow::ShadowLeafUpdates dependencyMapToShadowLeafUpdates(core::DependencyMap& dependencyMap);
29
29
 
30
30
  private:
@@ -1,12 +1,14 @@
1
1
  #if os(iOS)
2
2
 
3
3
  import Foundation
4
+ import Combine
4
5
  import NitroModules
5
6
 
6
7
  typealias CxxListener = (Array<UnistyleDependency>) -> Void
7
8
 
8
9
  class NativeIOSPlatform: HybridNativePlatformSpec {
9
10
  var miniRuntime: UnistylesNativeMiniRuntime?
11
+ var cancellables = Set<AnyCancellable>()
10
12
 
11
13
  var listeners: Array<CxxListener> = []
12
14
  var hybridContext = margelo.nitro.HybridContext()
@@ -2,16 +2,18 @@ import Foundation
2
2
 
3
3
  extension NativeIOSPlatform {
4
4
  func setupPlatformListeners() {
5
- NotificationCenter.default.addObserver(
6
- self,
7
- selector: #selector(onWindowChange(_:)),
8
- name: NSNotification.Name("RCTWindowFrameDidChangeNotification"),
9
- object: nil
10
- )
5
+ NotificationCenter.default.publisher(for: NSNotification.Name("RCTWindowFrameDidChangeNotification"))
6
+ // add small delay (10ms) to make sure all values are up ot date
7
+ // we MUST call it on current thread, otherwise random crashes occurs
8
+ .delay(for: .milliseconds(10), scheduler: RunLoop.current)
9
+ .sink { [weak self] notification in
10
+ self?.onWindowChange(notification)
11
+ }
12
+ .store(in: &cancellables)
11
13
  }
12
14
 
13
15
  func removePlatformListeners() {
14
- NotificationCenter.default.removeObserver(self, name: NSNotification.Name("RCTWindowFrameDidChangeNotification"), object: nil)
16
+ cancellables.removeAll()
15
17
  }
16
18
 
17
19
  func registerPlatformListener(callback: @escaping (CxxListener)) throws {
@@ -24,18 +26,16 @@ extension NativeIOSPlatform {
24
26
 
25
27
  @objc func onWindowChange(_ notification: Notification) {
26
28
  // add small delay (10ms) to make sure all values are up ot date
27
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
28
- guard let currentMiniRuntime = self.miniRuntime else {
29
- return
30
- }
31
-
32
- let newMiniRuntime = self.buildMiniRuntime()
33
- let changedDependencies = UnistylesNativeMiniRuntime.diff(lhs: currentMiniRuntime, rhs: newMiniRuntime)
34
-
35
- if (changedDependencies.count > 0) {
36
- self.miniRuntime = newMiniRuntime
37
- self.emitCxxEvent(dependencies: changedDependencies)
38
- }
29
+ guard let currentMiniRuntime = self.miniRuntime else {
30
+ return
31
+ }
32
+
33
+ let newMiniRuntime = self.buildMiniRuntime()
34
+ let changedDependencies = UnistylesNativeMiniRuntime.diff(lhs: currentMiniRuntime, rhs: newMiniRuntime)
35
+
36
+ if (changedDependencies.count > 0) {
37
+ self.miniRuntime = newMiniRuntime
38
+ self.emitCxxEvent(dependencies: changedDependencies)
39
39
  }
40
40
  }
41
41
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-unistyles",
3
- "version": "3.0.0-alpha.22",
3
+ "version": "3.0.0-alpha.24",
4
4
  "description": "Level up your React Native StyleSheet",
5
5
  "scripts": {
6
6
  "test": "jest",