• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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