• 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 
22 namespace OHOS::Ace::Framework {
23 
24 namespace {
25 // navigation title bar options
26 constexpr char BACKGROUND_COLOR_PROPERTY[] = "backgroundColor";
27 constexpr char BACKGROUND_BLUR_STYLE_PROPERTY[] = "backgroundBlurStyle";
28 constexpr char BACKGROUND_BLUR_STYLE_OPTIONS_PROPERTY[] = "backgroundBlurStyleOptions";
29 constexpr char BACKGROUND_EFFECT_PROPERTY[] = "backgroundEffect";
30 constexpr char BAR_STYLE_PROPERTY[] = "barStyle";
31 constexpr char PADDING_START_PROPERTY[] = "paddingStart";
32 constexpr char PADDING_END_PROPERTY[] = "paddingEnd";
33 constexpr char MAIN_TITLE_MODIFIER[] = "mainTitleModifier";
34 constexpr char SUB_TITLE_MODIFIER[] = "subTitleModifier";
35 constexpr char TEXT_HIDE_PROPERTY[] = "hideItemValue";
36 
ParseSymbolAndIcon(const JSCallbackInfo & info,NG::BarItem & toolBarItem,const JSRef<JSObject> & itemObject)37 void ParseSymbolAndIcon(const JSCallbackInfo& info, NG::BarItem& toolBarItem,
38     const JSRef<JSObject>& itemObject)
39 {
40     std::string icon;
41     std::string activeIcon;
42     auto itemSymbolIconObject = itemObject->GetProperty("symbolIcon");
43     if (itemSymbolIconObject->IsObject()) {
44         std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
45         JSViewAbstract::SetSymbolOptionApply(info, iconSymbol, itemSymbolIconObject);
46         toolBarItem.iconSymbol = iconSymbol;
47     }
48     auto itemIconObject = itemObject->GetProperty("icon");
49     if (JSViewAbstract::ParseJsMedia(itemIconObject, icon)) {
50         toolBarItem.icon = icon;
51     }
52 
53     auto itemActiveSymbolIconObject = itemObject->GetProperty("activeSymbolIcon");
54     if (itemActiveSymbolIconObject->IsObject()) {
55         std::function<void(WeakPtr<NG::FrameNode>)> activeSymbol = nullptr;
56         JSViewAbstract::SetSymbolOptionApply(info, activeSymbol, itemActiveSymbolIconObject);
57         toolBarItem.activeIconSymbol = activeSymbol;
58     }
59     auto itemActiveIconObject = itemObject->GetProperty("activeIcon");
60     if (JSViewAbstract::ParseJsMedia(itemActiveIconObject, activeIcon)) {
61         toolBarItem.activeIcon = activeIcon;
62     }
63 }
64 
ParseBackgroundOptions(const JSRef<JSVal> & obj,NG::NavigationBackgroundOptions & options)65 void ParseBackgroundOptions(const JSRef<JSVal>& obj, NG::NavigationBackgroundOptions& options)
66 {
67     options.color.reset();
68     options.blurStyleOption.reset();
69     options.effectOption.reset();
70     if (!obj->IsObject()) {
71         return;
72     }
73     auto optObj = JSRef<JSObject>::Cast(obj);
74     auto colorProperty = optObj->GetProperty(BACKGROUND_COLOR_PROPERTY);
75     Color color;
76     if (JSViewAbstract::ParseJsColor(colorProperty, color)) {
77         options.color = color;
78     }
79     BlurStyleOption styleOptions;
80     auto blurProperty = optObj->GetProperty(BACKGROUND_BLUR_STYLE_PROPERTY);
81     if (blurProperty->IsNumber()) {
82         auto blurStyle = blurProperty->ToNumber<int32_t>();
83         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
84             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
85             styleOptions.blurStyle = static_cast<BlurStyle>(blurStyle);
86         }
87     }
88     auto blurOptionProperty = optObj->GetProperty(BACKGROUND_BLUR_STYLE_OPTIONS_PROPERTY);
89     if (blurOptionProperty->IsObject()) {
90         JSViewAbstract::ParseBlurStyleOption(blurOptionProperty, styleOptions);
91     }
92     options.blurStyleOption = styleOptions;
93     auto effectProperty = optObj->GetProperty(BACKGROUND_EFFECT_PROPERTY);
94     if (effectProperty->IsObject()) {
95         EffectOption effectOption;
96         JSViewAbstract::ParseEffectOption(effectProperty, effectOption);
97         options.effectOption = effectOption;
98     }
99 }
100 
ParseBarOptions(const JSRef<JSVal> & obj,NG::NavigationBarOptions & options)101 void ParseBarOptions(const JSRef<JSVal>& obj, NG::NavigationBarOptions& options)
102 {
103     options.paddingStart.reset();
104     options.paddingEnd.reset();
105     options.barStyle.reset();
106     if (!obj->IsObject()) {
107         return;
108     }
109     auto optObj = JSRef<JSObject>::Cast(obj);
110     auto barStyleProperty = optObj->GetProperty(BAR_STYLE_PROPERTY);
111     if (barStyleProperty->IsNumber()) {
112         auto barStyle = barStyleProperty->ToNumber<int32_t>();
113         if (barStyle >= static_cast<int32_t>(NG::BarStyle::STANDARD) &&
114             barStyle <= static_cast<int32_t>(NG::BarStyle::SAFE_AREA_PADDING)) {
115             options.barStyle = static_cast<NG::BarStyle>(barStyle);
116         } else {
117             options.barStyle = NG::BarStyle::STANDARD;
118         }
119     }
120     CalcDimension paddingStart;
121     if (JSViewAbstract::ParseLengthMetricsToDimension(optObj->GetProperty(PADDING_START_PROPERTY), paddingStart)) {
122         options.paddingStart = paddingStart;
123     }
124     CalcDimension paddingEnd;
125     if (JSViewAbstract::ParseLengthMetricsToDimension(optObj->GetProperty(PADDING_END_PROPERTY), paddingEnd)) {
126         options.paddingEnd = paddingEnd;
127     }
128 }
129 
ParseTextOptions(const JSCallbackInfo & info,const JSRef<JSVal> & obj,NG::NavigationTextOptions & options)130 void ParseTextOptions(const JSCallbackInfo& info, const JSRef<JSVal>& obj, NG::NavigationTextOptions& options)
131 {
132     options.Reset();
133     if (!obj->IsObject()) {
134         return;
135     }
136     auto optObj = JSRef<JSObject>::Cast(obj);
137     auto mainTitleModifierProperty = optObj->GetProperty(MAIN_TITLE_MODIFIER);
138     auto subTitleModifierProperty = optObj->GetProperty(SUB_TITLE_MODIFIER);
139     JSViewAbstract::SetTextStyleApply(info, options.mainTitleApplyFunc, mainTitleModifierProperty);
140     JSViewAbstract::SetTextStyleApply(info, options.subTitleApplyFunc, subTitleModifierProperty);
141 }
142 
ParseToolBarItemAction(const WeakPtr<NG::FrameNode> & targetNode,const JSCallbackInfo & info,const JSRef<JSObject> & itemObject,NG::BarItem & toolBarItem)143 void ParseToolBarItemAction(const WeakPtr<NG::FrameNode>& targetNode,
144     const JSCallbackInfo& info, const JSRef<JSObject>& itemObject, NG::BarItem& toolBarItem)
145 {
146     auto itemActionValue = itemObject->GetProperty("action");
147     if (!itemActionValue->IsFunction()) {
148         return;
149     }
150 
151     RefPtr<JsFunction> onClickFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(itemActionValue));
152     auto onItemClick = [execCtx = info.GetExecutionContext(), func = std::move(onClickFunc),
153                             node = targetNode]() {
154         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
155         if (func) {
156             PipelineContext::SetCallBackNode(node);
157             func->ExecuteJS();
158         }
159     };
160     toolBarItem.action = onItemClick;
161 }
162 }
163 
ParseToolbarItemsConfiguration(const WeakPtr<NG::FrameNode> & targetNode,const JSCallbackInfo & info,const JSRef<JSArray> & jsArray,std::vector<NG::BarItem> & items)164 void JSNavigationUtils::ParseToolbarItemsConfiguration(const WeakPtr<NG::FrameNode>& targetNode,
165     const JSCallbackInfo& info, const JSRef<JSArray>& jsArray, std::vector<NG::BarItem>& items)
166 {
167     auto length = jsArray->Length();
168     for (size_t i = 0; i < length; i++) {
169         auto item = jsArray->GetValueAt(i);
170         if (!item->IsObject()) {
171             continue;
172         }
173 
174         NG::BarItem toolBarItem;
175         std::string text;
176         auto itemObject = JSRef<JSObject>::Cast(item);
177         auto itemValueObject = itemObject->GetProperty("value");
178         if (JSViewAbstract::ParseJsString(itemValueObject, text)) {
179             toolBarItem.text = text;
180         }
181 
182         ParseToolBarItemAction(targetNode, info, itemObject, toolBarItem);
183 
184         auto itemStatusValue = itemObject->GetProperty("status");
185         if (itemStatusValue->IsNumber()) {
186             toolBarItem.status = static_cast<NG::NavToolbarItemStatus>(itemStatusValue->ToNumber<int32_t>());
187         }
188         ParseSymbolAndIcon(info, toolBarItem, itemObject);
189         items.push_back(toolBarItem);
190     }
191 }
192 
ParseTitleBarOptions(const JSCallbackInfo & info,bool needSetDefaultValue,NG::NavigationTitlebarOptions & options)193 void JSNavigationUtils::ParseTitleBarOptions(
194     const JSCallbackInfo& info, bool needSetDefaultValue, NG::NavigationTitlebarOptions& options)
195 {
196     if (needSetDefaultValue) {
197         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
198             auto pipelineContext = PipelineBase::GetCurrentContext();
199             CHECK_NULL_VOID(pipelineContext);
200             auto theme = pipelineContext->GetTheme<NavigationBarTheme>();
201             CHECK_NULL_VOID(theme);
202             auto blurStyle = static_cast<BlurStyle>(theme->GetTitlebarBackgroundBlurStyle());
203             if (blurStyle != BlurStyle::NO_MATERIAL) {
204                 BlurStyleOption blurStyleOption;
205                 blurStyleOption.blurStyle = blurStyle;
206                 options.bgOptions.blurStyleOption = blurStyleOption;
207                 options.bgOptions.color = Color::TRANSPARENT;
208             }
209         }
210     }
211 
212     if (info.Length() > 1) {
213         if (!info[1]->IsObject()) {
214             return;
215         }
216         ParseBackgroundOptions(info[1], options.bgOptions);
217         ParseBarOptions(info[1], options.brOptions);
218         ParseTextOptions(info, info[1], options.textOptions);
219         JSRef<JSObject> jsObjOption = JSRef<JSObject>::Cast(info[1]);
220         auto enableHoverModeProperty = jsObjOption->GetProperty("enableHoverMode");
221         if (enableHoverModeProperty->IsBoolean()) {
222             options.enableHoverMode = enableHoverModeProperty->ToBoolean();
223         }
224     }
225 }
226 
ParseToolbarOptions(const JSCallbackInfo & info,NG::NavigationToolbarOptions & options)227 void JSNavigationUtils::ParseToolbarOptions(const JSCallbackInfo& info, NG::NavigationToolbarOptions& options)
228 {
229     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
230         auto pipelineContext = PipelineBase::GetCurrentContext();
231         CHECK_NULL_VOID(pipelineContext);
232         auto theme = pipelineContext->GetTheme<NavigationBarTheme>();
233         CHECK_NULL_VOID(theme);
234         auto blurStyle = static_cast<BlurStyle>(theme->GetToolbarBackgroundBlurStyle());
235         if (blurStyle != BlurStyle::NO_MATERIAL) {
236             BlurStyleOption blurStyleOption;
237             blurStyleOption.blurStyle = blurStyle;
238             options.bgOptions.blurStyleOption = blurStyleOption;
239             options.bgOptions.color = Color::TRANSPARENT;
240         }
241     }
242     if (info.Length() > 1) {
243         ParseBackgroundOptions(info[1], options.bgOptions);
244         ParseBarOptions(info[1], options.brOptions);
245     }
246 }
247 
ParseHideToolBarText(const JSCallbackInfo & info,bool & hideText)248 void JSNavigationUtils::ParseHideToolBarText(const JSCallbackInfo& info, bool& hideText)
249 {
250     if (info.Length() > 1) {
251         if (!info[1]->IsObject()) {
252             return;
253         }
254         auto optObj = JSRef<JSObject>::Cast(info[1]);
255         auto hideTextProperty = optObj->GetProperty(TEXT_HIDE_PROPERTY);
256         bool isHideText;
257         if (JSViewAbstract::ParseJsBool(hideTextProperty, isHideText)) {
258             hideText = isHideText;
259         }
260     }
261 }
262 
ParseToolBarMoreButtonOptions(const JSRef<JSVal> & optObj,NG::MoreButtonOptions & options)263 void JSNavigationUtils::ParseToolBarMoreButtonOptions(const JSRef<JSVal>& optObj, NG::MoreButtonOptions& options)
264 {
265     if (optObj->IsObject()) {
266         NG::NavigationBackgroundOptions moreButtonBackgroundOptions;
267         ParseBackgroundOptions(optObj, moreButtonBackgroundOptions);
268         options.bgOptions = moreButtonBackgroundOptions;
269     }
270 }
271 
ParseMenuOptions(const JSRef<JSVal> & optObj,NG::NavigationMenuOptions & options)272 void JSNavigationUtils::ParseMenuOptions(const JSRef<JSVal>& optObj, NG::NavigationMenuOptions& options)
273 {
274     if (optObj->IsObject()) {
275         // set more button options.
276         NG::NavigationBackgroundOptions moreButtonBackgroundOptions;
277         ParseBackgroundOptions(optObj, moreButtonBackgroundOptions);
278         options.mbOptions.bgOptions = moreButtonBackgroundOptions;
279     }
280 }
281 
ParseBarItems(const WeakPtr<NG::FrameNode> & targetNode,const JSCallbackInfo & info,const JSRef<JSArray> & jsArray,std::vector<NG::BarItem> & items)282 void JSNavigationUtils::ParseBarItems(const WeakPtr<NG::FrameNode>& targetNode,
283     const JSCallbackInfo& info, const JSRef<JSArray>& jsArray, std::vector<NG::BarItem>& items)
284 {
285     auto length = jsArray->Length();
286     for (size_t i = 0; i < length; i++) {
287         auto item = jsArray->GetValueAt(i);
288         if (!item->IsObject()) {
289             continue;
290         }
291         auto itemObject = JSRef<JSObject>::Cast(item);
292         NG::BarItem toolBarItem;
293         std::string value;
294         auto itemValueObject = itemObject->GetProperty("value");
295         if (JSViewAbstract::ParseJsString(itemValueObject, value)) {
296             toolBarItem.text = value;
297         }
298 
299         auto itemSymbolIconObject = itemObject->GetProperty("symbolIcon");
300         if (itemSymbolIconObject->IsObject()) {
301             std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
302             JSViewAbstract::SetSymbolOptionApply(info, iconSymbol, itemSymbolIconObject);
303             toolBarItem.iconSymbol = iconSymbol;
304         }
305         std::string icon;
306         auto itemIconObject = itemObject->GetProperty("icon");
307         if (JSViewAbstract::ParseJsMedia(itemIconObject, icon)) {
308             toolBarItem.icon = icon;
309         }
310 
311         auto itemEnabledObject = itemObject->GetProperty("isEnabled");
312         if (itemEnabledObject->IsBoolean()) {
313             toolBarItem.isEnabled = itemEnabledObject->ToBoolean();
314         }
315 
316         ParseToolBarItemAction(targetNode, info, itemObject, toolBarItem);
317         items.push_back(toolBarItem);
318     }
319 }
320 
ParseNavDestinationTransition(const JSRef<JSObject> & jsTransition,const JsiExecutionContext & execCtx)321 std::optional<NG::NavDestinationTransition> JSNavigationUtils::ParseNavDestinationTransition(
322     const JSRef<JSObject>& jsTransition, const JsiExecutionContext& execCtx)
323 {
324     if (jsTransition->IsEmpty() || jsTransition->IsUndefined()) {
325         return std::nullopt;
326     }
327     NG::NavDestinationTransition navDestinationTransition;
328     JSRef<JSVal> event = jsTransition->GetProperty("event");
329     if (!event->IsFunction()) {
330         // property `event` of navDestinationTransition is required option, so return nullopt if it's invalid.
331         return std::nullopt;
332     } else {
333         auto eventFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(event));
334         auto transitionEvent = [execCtx, event = std::move(eventFunc)]() {
335             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
336             ACE_SCORING_EVENT("navDestination custom transition event");
337             event->ExecuteJS();
338         };
339         navDestinationTransition.event = std::move(transitionEvent);
340     }
341     JSRef<JSVal> jsOnTransitionEnd = jsTransition->GetProperty("onTransitionEnd");
342     if (jsOnTransitionEnd->IsFunction()) {
343         auto transitionEndFunc =
344             AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(jsOnTransitionEnd));
345         auto onTransitionEnd = [execCtx, transitionEnd = std::move(transitionEndFunc)]() {
346             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
347             ACE_SCORING_EVENT("navDestination custom transition finish");
348             transitionEnd->ExecuteJS();
349         };
350         navDestinationTransition.onTransitionEnd = std::move(onTransitionEnd);
351     }
352     JSRef<JSVal> duration = jsTransition->GetProperty("duration");
353     // default duration: 1000.
354     navDestinationTransition.duration = duration->IsNumber() ? duration->ToNumber<int32_t>() : 1000;
355     JSRef<JSVal> delay = jsTransition->GetProperty("delay");
356     // default delay: 0.
357     navDestinationTransition.delay = delay->IsNumber() ? delay->ToNumber<int32_t>() : 0;
358     JSRef<JSVal> curveArgs = jsTransition->GetProperty("curve");
359     if (curveArgs->IsString()) {
360         navDestinationTransition.curve = CreateCurve(curveArgs->ToString(), false);
361     } else if (curveArgs->IsObject()) {
362         JSRef<JSVal> curveString = JSRef<JSObject>::Cast(curveArgs)->GetProperty("__curveString");
363         if (curveString->IsString()) {
364             navDestinationTransition.curve = CreateCurve(curveString->ToString(), false);
365         }
366     } else {
367         // default curve: easeInOut
368         navDestinationTransition.curve = Curves::EASE_IN_OUT;
369     }
370     return navDestinationTransition;
371 }
372 } // namespace OHOS::Ace::Framework
373