1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "frameworks/bridge/declarative_frontend/jsview/js_navigation_utils.h"
17
18 #include "frameworks/base/log/ace_scoring_log.h"
19 #include "bridge/declarative_frontend/jsview/js_utils.h"
20 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
21 #include "core/common/resource/resource_parse_utils.h"
22
23 namespace OHOS::Ace::Framework {
24
25 namespace {
26 // navigation title bar options
27 constexpr char BACKGROUND_COLOR_PROPERTY[] = "backgroundColor";
28 constexpr char BACKGROUND_BLUR_STYLE_PROPERTY[] = "backgroundBlurStyle";
29 constexpr char BACKGROUND_BLUR_STYLE_OPTIONS_PROPERTY[] = "backgroundBlurStyleOptions";
30 constexpr char BACKGROUND_EFFECT_PROPERTY[] = "backgroundEffect";
31 constexpr char BAR_STYLE_PROPERTY[] = "barStyle";
32 constexpr char PADDING_START_PROPERTY[] = "paddingStart";
33 constexpr char PADDING_END_PROPERTY[] = "paddingEnd";
34 constexpr char MAIN_TITLE_MODIFIER[] = "mainTitleModifier";
35 constexpr char SUB_TITLE_MODIFIER[] = "subTitleModifier";
36 constexpr char TEXT_HIDE_PROPERTY[] = "hideItemValue";
37
ParseSymbolAndIcon(const JSCallbackInfo & info,NG::BarItem & toolBarItem,const JSRef<JSObject> & itemObject)38 void ParseSymbolAndIcon(const JSCallbackInfo& info, NG::BarItem& toolBarItem,
39 const JSRef<JSObject>& itemObject)
40 {
41 std::string icon;
42 std::string activeIcon;
43 auto itemSymbolIconObject = itemObject->GetProperty("symbolIcon");
44 if (itemSymbolIconObject->IsObject()) {
45 std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
46 JSViewAbstract::SetSymbolOptionApply(info, iconSymbol, itemSymbolIconObject);
47 toolBarItem.iconSymbol = iconSymbol;
48 }
49 auto itemIconObject = itemObject->GetProperty("icon");
50 RefPtr<ResourceObject> iconResObj;
51 if (JSViewAbstract::ParseJsMedia(itemIconObject, icon, iconResObj)) {
52 toolBarItem.icon = icon;
53 }
54 if (iconResObj && SystemProperties::ConfigChangePerform()) {
55 auto&& updateFunc = [](const RefPtr<ResourceObject>& iconResObj, NG::BarItem& toolBarItem) {
56 std::string result;
57 if (ResourceParseUtils::ParseResMedia(iconResObj, result)) {
58 toolBarItem.icon = result;
59 }
60 };
61 toolBarItem.AddResource("navigation.toolbarItem.iconResObj", iconResObj, std::move(updateFunc));
62 }
63
64 auto itemActiveSymbolIconObject = itemObject->GetProperty("activeSymbolIcon");
65 if (itemActiveSymbolIconObject->IsObject()) {
66 std::function<void(WeakPtr<NG::FrameNode>)> activeSymbol = nullptr;
67 JSViewAbstract::SetSymbolOptionApply(info, activeSymbol, itemActiveSymbolIconObject);
68 toolBarItem.activeIconSymbol = activeSymbol;
69 }
70 auto itemActiveIconObject = itemObject->GetProperty("activeIcon");
71
72 RefPtr<ResourceObject> activeIconResObj;
73 if (JSViewAbstract::ParseJsMedia(itemActiveIconObject, activeIcon, activeIconResObj)) {
74 toolBarItem.activeIcon = activeIcon;
75 }
76 if (activeIconResObj && SystemProperties::ConfigChangePerform()) {
77 auto&& updateFunc = [](const RefPtr<ResourceObject>& activeIconResObj, NG::BarItem& toolBarItem) {
78 std::string result;
79 if (ResourceParseUtils::ParseResMedia(activeIconResObj, result)) {
80 toolBarItem.activeIcon = result;
81 }
82 };
83 toolBarItem.AddResource("navigation.toolbarItem.activeIconResObj", activeIconResObj, std::move(updateFunc));
84 }
85 }
86
UpdateNavigationBackgroundColor(const JSRef<JSObject> & optObj,Color & color,NG::NavigationBackgroundOptions & options)87 void UpdateNavigationBackgroundColor(
88 const JSRef<JSObject>& optObj, Color& color, NG::NavigationBackgroundOptions& options)
89 {
90 auto colorProperty = optObj->GetProperty(BACKGROUND_COLOR_PROPERTY);
91 if (!SystemProperties::ConfigChangePerform()) {
92 if (JSViewAbstract::ParseJsColor(colorProperty, color)) {
93 options.color = color;
94 }
95 return;
96 }
97 RefPtr<ResourceObject> backgroundColorResObj;
98 if (JSViewAbstract::ParseJsColor(colorProperty, color, backgroundColorResObj)) {
99 options.color = color;
100 }
101 if (backgroundColorResObj) {
102 auto&& updateBackgroundColorFunc = [](const RefPtr<ResourceObject>& resObj,
103 NG::NavigationBackgroundOptions& options) {
104 Color backgroundColor;
105 if (ResourceParseUtils::ParseResColor(resObj, backgroundColor)) {
106 options.color = backgroundColor;
107 }
108 };
109 options.AddResource(
110 "navigationTitleOptions.backgroundColor", backgroundColorResObj, std::move(updateBackgroundColorFunc));
111 }
112 }
113
ParseBackgroundOptions(const JSRef<JSVal> & obj,NG::NavigationBackgroundOptions & options)114 void ParseBackgroundOptions(const JSRef<JSVal>& obj, NG::NavigationBackgroundOptions& options)
115 {
116 options.color.reset();
117 options.blurStyleOption.reset();
118 options.effectOption.reset();
119 options.resMap_.clear();
120 if (!obj->IsObject()) {
121 return;
122 }
123 auto optObj = JSRef<JSObject>::Cast(obj);
124 Color color;
125 UpdateNavigationBackgroundColor(optObj, color, options);
126 BlurStyleOption styleOptions;
127 auto blurProperty = optObj->GetProperty(BACKGROUND_BLUR_STYLE_PROPERTY);
128 if (blurProperty->IsNumber()) {
129 auto blurStyle = blurProperty->ToNumber<int32_t>();
130 if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
131 blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
132 styleOptions.blurStyle = static_cast<BlurStyle>(blurStyle);
133 }
134 }
135 auto blurOptionProperty = optObj->GetProperty(BACKGROUND_BLUR_STYLE_OPTIONS_PROPERTY);
136 if (blurOptionProperty->IsObject()) {
137 JSViewAbstract::ParseBlurStyleOption(blurOptionProperty, styleOptions);
138 }
139 options.blurStyleOption = styleOptions;
140 auto effectProperty = optObj->GetProperty(BACKGROUND_EFFECT_PROPERTY);
141 if (effectProperty->IsObject()) {
142 EffectOption effectOption;
143 JSViewAbstract::ParseEffectOption(effectProperty, effectOption);
144 options.effectOption = effectOption;
145 }
146 }
147
ParseBarOptions(const JSRef<JSVal> & obj,NG::NavigationBarOptions & options)148 void ParseBarOptions(const JSRef<JSVal>& obj, NG::NavigationBarOptions& options)
149 {
150 options.paddingStart.reset();
151 options.paddingEnd.reset();
152 options.barStyle.reset();
153 if (!obj->IsObject()) {
154 return;
155 }
156 auto optObj = JSRef<JSObject>::Cast(obj);
157 auto barStyleProperty = optObj->GetProperty(BAR_STYLE_PROPERTY);
158 if (barStyleProperty->IsNumber()) {
159 auto barStyle = barStyleProperty->ToNumber<int32_t>();
160 if (barStyle >= static_cast<int32_t>(NG::BarStyle::STANDARD) &&
161 barStyle <= static_cast<int32_t>(NG::BarStyle::SAFE_AREA_PADDING)) {
162 options.barStyle = static_cast<NG::BarStyle>(barStyle);
163 } else {
164 options.barStyle = NG::BarStyle::STANDARD;
165 }
166 }
167 CalcDimension paddingStart;
168 if (JSViewAbstract::ParseLengthMetricsToDimension(optObj->GetProperty(PADDING_START_PROPERTY), paddingStart)) {
169 options.paddingStart = paddingStart;
170 }
171 CalcDimension paddingEnd;
172 if (JSViewAbstract::ParseLengthMetricsToDimension(optObj->GetProperty(PADDING_END_PROPERTY), paddingEnd)) {
173 options.paddingEnd = paddingEnd;
174 }
175 }
176
ParseTextOptions(const JSCallbackInfo & info,const JSRef<JSVal> & obj,NG::NavigationTextOptions & options)177 void ParseTextOptions(const JSCallbackInfo& info, const JSRef<JSVal>& obj, NG::NavigationTextOptions& options)
178 {
179 options.Reset();
180 if (!obj->IsObject()) {
181 return;
182 }
183 auto optObj = JSRef<JSObject>::Cast(obj);
184 auto mainTitleModifierProperty = optObj->GetProperty(MAIN_TITLE_MODIFIER);
185 auto subTitleModifierProperty = optObj->GetProperty(SUB_TITLE_MODIFIER);
186 JSViewAbstract::SetTextStyleApply(info, options.mainTitleApplyFunc, mainTitleModifierProperty);
187 JSViewAbstract::SetTextStyleApply(info, options.subTitleApplyFunc, subTitleModifierProperty);
188 }
189
ParseToolBarItemAction(const WeakPtr<NG::FrameNode> & targetNode,const JSCallbackInfo & info,const JSRef<JSObject> & itemObject,NG::BarItem & toolBarItem)190 void ParseToolBarItemAction(const WeakPtr<NG::FrameNode>& targetNode,
191 const JSCallbackInfo& info, const JSRef<JSObject>& itemObject, NG::BarItem& toolBarItem)
192 {
193 auto itemActionValue = itemObject->GetProperty("action");
194 if (!itemActionValue->IsFunction()) {
195 return;
196 }
197
198 RefPtr<JsFunction> onClickFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(itemActionValue));
199 auto onItemClick = [execCtx = info.GetExecutionContext(), func = std::move(onClickFunc),
200 node = targetNode]() {
201 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
202 if (func) {
203 PipelineContext::SetCallBackNode(node);
204 func->ExecuteJS();
205 }
206 };
207 toolBarItem.action = onItemClick;
208 }
209
UpdateToolBarItemText(const JSRef<JSObject> & itemObject,NG::BarItem & toolBarItem)210 void UpdateToolBarItemText(const JSRef<JSObject>& itemObject, NG::BarItem& toolBarItem)
211 {
212 std::string text;
213 auto itemValueObject = itemObject->GetProperty("value");
214 RefPtr<ResourceObject> navigationResObj;
215 if (JSViewAbstract::ParseJsString(itemValueObject, text, navigationResObj)) {
216 toolBarItem.text = text;
217 }
218 if (navigationResObj && SystemProperties::ConfigChangePerform()) {
219 auto&& updateFunc = [](const RefPtr<ResourceObject>& navigationResObj, NG::BarItem& toolBarItem) {
220 std::string result;
221 if (ResourceParseUtils::ParseResString(navigationResObj, result)) {
222 toolBarItem.text = result;
223 }
224 };
225 toolBarItem.AddResource("navigation.toolbarItem.textResObj", navigationResObj, std::move(updateFunc));
226 }
227 }
228
ParseBarItemsValue(const JSRef<JSObject> & itemObject,NG::BarItem & toolBarItem)229 void ParseBarItemsValue(const JSRef<JSObject>& itemObject, NG::BarItem& toolBarItem)
230 {
231 std::string value;
232 auto itemValueObject = itemObject->GetProperty("value");
233 RefPtr<ResourceObject> itemValueResObj;
234 if (JSViewAbstract::ParseJsString(itemValueObject, value, itemValueResObj)) {
235 toolBarItem.text = value;
236 }
237 if (itemValueResObj && SystemProperties::ConfigChangePerform()) {
238 auto&& updateFunc = [](const RefPtr<ResourceObject>& itemValueResObj, NG::BarItem& toolBarItem) {
239 std::string valueResult;
240 if (ResourceParseUtils::ParseResString(itemValueResObj, valueResult)) {
241 toolBarItem.text = valueResult;
242 }
243 };
244 toolBarItem.AddResource("toolBarItem.value", itemValueResObj, std::move(updateFunc));
245 }
246 }
247
ParseBarItemsIcon(const JSRef<JSObject> & itemObject,NG::BarItem & toolBarItem)248 void ParseBarItemsIcon(const JSRef<JSObject>& itemObject, NG::BarItem& toolBarItem)
249 {
250 std::string icon;
251 auto itemIconObject = itemObject->GetProperty("icon");
252 RefPtr<ResourceObject> itemIconResObj;
253 if (JSViewAbstract::ParseJsMedia(itemIconObject, icon, itemIconResObj)) {
254 toolBarItem.icon = icon;
255 }
256 if (itemIconResObj && SystemProperties::ConfigChangePerform()) {
257 auto&& updateFunc = [](const RefPtr<ResourceObject>& itemIconResObj, NG::BarItem& toolBarItem) {
258 std::string iconResult;
259 if (ResourceParseUtils::ParseResMedia(itemIconResObj, iconResult)) {
260 toolBarItem.icon = iconResult;
261 }
262 };
263 toolBarItem.AddResource("navigation.barItem.icon", itemIconResObj, std::move(updateFunc));
264 }
265 }
266 }
267
ParseToolbarItemsConfiguration(const WeakPtr<NG::FrameNode> & targetNode,const JSCallbackInfo & info,const JSRef<JSArray> & jsArray,std::vector<NG::BarItem> & items)268 void JSNavigationUtils::ParseToolbarItemsConfiguration(const WeakPtr<NG::FrameNode>& targetNode,
269 const JSCallbackInfo& info, const JSRef<JSArray>& jsArray, std::vector<NG::BarItem>& items)
270 {
271 auto length = jsArray->Length();
272 for (size_t i = 0; i < length; i++) {
273 auto item = jsArray->GetValueAt(i);
274 if (!item->IsObject()) {
275 continue;
276 }
277
278 NG::BarItem toolBarItem;
279 auto itemObject = JSRef<JSObject>::Cast(item);
280 UpdateToolBarItemText(itemObject, toolBarItem);
281 ParseToolBarItemAction(targetNode, info, itemObject, toolBarItem);
282
283 auto itemStatusValue = itemObject->GetProperty("status");
284 if (itemStatusValue->IsNumber()) {
285 toolBarItem.status = static_cast<NG::NavToolbarItemStatus>(itemStatusValue->ToNumber<int32_t>());
286 }
287 ParseSymbolAndIcon(info, toolBarItem, itemObject);
288 items.push_back(toolBarItem);
289 }
290 }
291
ParseTitleBarOptions(const JSCallbackInfo & info,bool needSetDefaultValue,NG::NavigationTitlebarOptions & options)292 void JSNavigationUtils::ParseTitleBarOptions(
293 const JSCallbackInfo& info, bool needSetDefaultValue, NG::NavigationTitlebarOptions& options)
294 {
295 if (needSetDefaultValue) {
296 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
297 auto pipelineContext = PipelineBase::GetCurrentContext();
298 CHECK_NULL_VOID(pipelineContext);
299 auto theme = pipelineContext->GetTheme<NavigationBarTheme>();
300 CHECK_NULL_VOID(theme);
301 auto blurStyle = static_cast<BlurStyle>(theme->GetTitlebarBackgroundBlurStyle());
302 if (blurStyle != BlurStyle::NO_MATERIAL) {
303 BlurStyleOption blurStyleOption;
304 blurStyleOption.blurStyle = blurStyle;
305 options.bgOptions.blurStyleOption = blurStyleOption;
306 options.bgOptions.color = Color::TRANSPARENT;
307 }
308 }
309 }
310
311 if (info.Length() > 1) {
312 if (!info[1]->IsObject()) {
313 return;
314 }
315 ParseBackgroundOptions(info[1], options.bgOptions);
316 ParseBarOptions(info[1], options.brOptions);
317 ParseTextOptions(info, info[1], options.textOptions);
318 JSRef<JSObject> jsObjOption = JSRef<JSObject>::Cast(info[1]);
319 auto enableHoverModeProperty = jsObjOption->GetProperty("enableHoverMode");
320 if (enableHoverModeProperty->IsBoolean()) {
321 options.enableHoverMode = enableHoverModeProperty->ToBoolean();
322 }
323 }
324 }
325
ParseToolbarOptions(const JSCallbackInfo & info,NG::NavigationToolbarOptions & options,const int32_t optionSituation)326 void JSNavigationUtils::ParseToolbarOptions(
327 const JSCallbackInfo& info, NG::NavigationToolbarOptions& options, const int32_t optionSituation)
328 {
329 if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
330 auto pipelineContext = PipelineBase::GetCurrentContext();
331 CHECK_NULL_VOID(pipelineContext);
332 auto theme = pipelineContext->GetTheme<NavigationBarTheme>();
333 CHECK_NULL_VOID(theme);
334 auto blurStyle = static_cast<BlurStyle>(theme->GetToolbarBackgroundBlurStyle());
335 if (blurStyle != BlurStyle::NO_MATERIAL) {
336 BlurStyleOption blurStyleOption;
337 blurStyleOption.blurStyle = blurStyle;
338 options.bgOptions.blurStyleOption = blurStyleOption;
339 options.bgOptions.color = Color::TRANSPARENT;
340 }
341 }
342 if (optionSituation < 0) {
343 return;
344 }
345 auto infoLength = static_cast<uint32_t>(optionSituation);
346 if (info.Length() > infoLength) {
347 ParseBackgroundOptions(info[optionSituation], options.bgOptions);
348 ParseBarOptions(info[optionSituation], options.brOptions);
349 }
350 }
351
ParseHideToolBarText(const JSCallbackInfo & info,bool & hideText)352 void JSNavigationUtils::ParseHideToolBarText(const JSCallbackInfo& info, bool& hideText)
353 {
354 if (info.Length() > 1) {
355 if (!info[1]->IsObject()) {
356 return;
357 }
358 auto optObj = JSRef<JSObject>::Cast(info[1]);
359 auto hideTextProperty = optObj->GetProperty(TEXT_HIDE_PROPERTY);
360 bool isHideText;
361 if (JSViewAbstract::ParseJsBool(hideTextProperty, isHideText)) {
362 hideText = isHideText;
363 }
364 }
365 }
366
ParseToolBarMoreButtonOptions(const JSRef<JSVal> & optObj,NG::MoreButtonOptions & options)367 void JSNavigationUtils::ParseToolBarMoreButtonOptions(const JSRef<JSVal>& optObj, NG::MoreButtonOptions& options)
368 {
369 if (optObj->IsObject()) {
370 NG::NavigationBackgroundOptions moreButtonBackgroundOptions;
371 ParseBackgroundOptions(optObj, moreButtonBackgroundOptions);
372 options.bgOptions = moreButtonBackgroundOptions;
373 }
374 }
375
ParseMenuOptions(const JSRef<JSVal> & optObj,NG::NavigationMenuOptions & options)376 void JSNavigationUtils::ParseMenuOptions(const JSRef<JSVal>& optObj, NG::NavigationMenuOptions& options)
377 {
378 if (optObj->IsObject()) {
379 // set more button options.
380 NG::NavigationBackgroundOptions moreButtonBackgroundOptions;
381 ParseBackgroundOptions(optObj, moreButtonBackgroundOptions);
382 options.mbOptions.bgOptions = moreButtonBackgroundOptions;
383 }
384 }
385
ParseBarItems(const WeakPtr<NG::FrameNode> & targetNode,const JSCallbackInfo & info,const JSRef<JSArray> & jsArray,std::vector<NG::BarItem> & items)386 void JSNavigationUtils::ParseBarItems(const WeakPtr<NG::FrameNode>& targetNode,
387 const JSCallbackInfo& info, const JSRef<JSArray>& jsArray, std::vector<NG::BarItem>& items)
388 {
389 auto length = jsArray->Length();
390 for (size_t i = 0; i < length; i++) {
391 auto item = jsArray->GetValueAt(i);
392 if (!item->IsObject()) {
393 continue;
394 }
395 auto itemObject = JSRef<JSObject>::Cast(item);
396 NG::BarItem toolBarItem;
397 ParseBarItemsValue(itemObject, toolBarItem);
398
399 auto itemSymbolIconObject = itemObject->GetProperty("symbolIcon");
400 if (itemSymbolIconObject->IsObject()) {
401 std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
402 JSViewAbstract::SetSymbolOptionApply(info, iconSymbol, itemSymbolIconObject);
403 toolBarItem.iconSymbol = iconSymbol;
404 }
405 ParseBarItemsIcon(itemObject, toolBarItem);
406
407 auto itemEnabledObject = itemObject->GetProperty("isEnabled");
408 if (itemEnabledObject->IsBoolean()) {
409 toolBarItem.isEnabled = itemEnabledObject->ToBoolean();
410 }
411
412 ParseToolBarItemAction(targetNode, info, itemObject, toolBarItem);
413 items.push_back(toolBarItem);
414 }
415 }
416
ParseNavDestinationTransition(const JSRef<JSObject> & jsTransition,const JsiExecutionContext & execCtx)417 std::optional<NG::NavDestinationTransition> JSNavigationUtils::ParseNavDestinationTransition(
418 const JSRef<JSObject>& jsTransition, const JsiExecutionContext& execCtx)
419 {
420 if (jsTransition->IsEmpty() || jsTransition->IsUndefined()) {
421 return std::nullopt;
422 }
423 NG::NavDestinationTransition navDestinationTransition;
424 JSRef<JSVal> event = jsTransition->GetProperty("event");
425 if (!event->IsFunction()) {
426 // property `event` of navDestinationTransition is required option, so return nullopt if it's invalid.
427 return std::nullopt;
428 } else {
429 auto eventFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(event));
430 auto transitionEvent = [execCtx, event = std::move(eventFunc)]() {
431 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
432 ACE_SCORING_EVENT("navDestination custom transition event");
433 event->ExecuteJS();
434 };
435 navDestinationTransition.event = std::move(transitionEvent);
436 }
437 JSRef<JSVal> jsOnTransitionEnd = jsTransition->GetProperty("onTransitionEnd");
438 if (jsOnTransitionEnd->IsFunction()) {
439 auto transitionEndFunc =
440 AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(jsOnTransitionEnd));
441 auto onTransitionEnd = [execCtx, transitionEnd = std::move(transitionEndFunc)]() {
442 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
443 ACE_SCORING_EVENT("navDestination custom transition finish");
444 transitionEnd->ExecuteJS();
445 };
446 navDestinationTransition.onTransitionEnd = std::move(onTransitionEnd);
447 }
448 JSRef<JSVal> duration = jsTransition->GetProperty("duration");
449 // default duration: 1000.
450 navDestinationTransition.duration = duration->IsNumber() ? duration->ToNumber<int32_t>() : 1000;
451 JSRef<JSVal> delay = jsTransition->GetProperty("delay");
452 // default delay: 0.
453 navDestinationTransition.delay = delay->IsNumber() ? delay->ToNumber<int32_t>() : 0;
454 JSRef<JSVal> curveArgs = jsTransition->GetProperty("curve");
455 if (curveArgs->IsString()) {
456 navDestinationTransition.curve = CreateCurve(curveArgs->ToString(), false);
457 } else if (curveArgs->IsObject()) {
458 JSRef<JSVal> curveString = JSRef<JSObject>::Cast(curveArgs)->GetProperty("__curveString");
459 if (curveString->IsString()) {
460 navDestinationTransition.curve = CreateCurve(curveString->ToString(), false);
461 }
462 } else {
463 // default curve: easeInOut
464 navDestinationTransition.curve = Curves::EASE_IN_OUT;
465 }
466 return navDestinationTransition;
467 }
468 } // namespace OHOS::Ace::Framework
469