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 "bridge/declarative_frontend/jsview/js_utils.h"
19 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
20 
21 namespace OHOS::Ace::Framework {
22 
23 namespace {
24 // navigation title bar options
25 constexpr char BACKGROUND_COLOR_PROPERTY[] = "backgroundColor";
26 constexpr char BACKGROUND_BLUR_STYLE_PROPERTY[] = "backgroundBlurStyle";
27 constexpr char BAR_STYLE_PROPERTY[] = "barStyle";
28 constexpr char PADDING_START_PROPERTY[] = "paddingStart";
29 constexpr char PADDING_END_PROPERTY[] = "paddingEnd";
30 constexpr char MAIN_TITLE_MODIFIER[] = "mainTitleModifier";
31 constexpr char SUB_TITLE_MODIFIER[] = "subTitleModifier";
32 
ParseSymbolAndIcon(const JSCallbackInfo & info,NG::BarItem & toolBarItem,const JSRef<JSObject> & itemObject)33 void ParseSymbolAndIcon(const JSCallbackInfo& info, NG::BarItem& toolBarItem,
34     const JSRef<JSObject>& itemObject)
35 {
36     std::string icon;
37     std::string activeIcon;
38     auto itemSymbolIconObject = itemObject->GetProperty("symbolIcon");
39     if (itemSymbolIconObject->IsObject()) {
40         std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
41         JSViewAbstract::SetSymbolOptionApply(info, iconSymbol, itemSymbolIconObject);
42         toolBarItem.iconSymbol = iconSymbol;
43     }
44     auto itemIconObject = itemObject->GetProperty("icon");
45     if (JSViewAbstract::ParseJsMedia(itemIconObject, icon)) {
46         toolBarItem.icon = icon;
47     }
48 
49     auto itemActiveSymbolIconObject = itemObject->GetProperty("activeSymbolIcon");
50     if (itemActiveSymbolIconObject->IsObject()) {
51         std::function<void(WeakPtr<NG::FrameNode>)> activeSymbol = nullptr;
52         JSViewAbstract::SetSymbolOptionApply(info, activeSymbol, itemActiveSymbolIconObject);
53         toolBarItem.activeIconSymbol = activeSymbol;
54     }
55     auto itemActiveIconObject = itemObject->GetProperty("activeIcon");
56     if (JSViewAbstract::ParseJsMedia(itemActiveIconObject, activeIcon)) {
57         toolBarItem.activeIcon = activeIcon;
58     }
59 }
60 
ParseBackgroundOptions(const JSRef<JSVal> & obj,NG::NavigationBackgroundOptions & options)61 void ParseBackgroundOptions(const JSRef<JSVal>& obj, NG::NavigationBackgroundOptions& options)
62 {
63     options.color.reset();
64     options.blurStyle.reset();
65     if (!obj->IsObject()) {
66         return;
67     }
68     auto optObj = JSRef<JSObject>::Cast(obj);
69     auto colorProperty = optObj->GetProperty(BACKGROUND_COLOR_PROPERTY);
70     Color color;
71     if (JSViewAbstract::ParseJsColor(colorProperty, color)) {
72         options.color = color;
73     }
74     auto blurProperty = optObj->GetProperty(BACKGROUND_BLUR_STYLE_PROPERTY);
75     if (blurProperty->IsNumber()) {
76         auto blurStyle = blurProperty->ToNumber<int32_t>();
77         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
78             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
79             options.blurStyle = static_cast<BlurStyle>(blurStyle);
80         }
81     }
82 }
83 
ParseBarOptions(const JSRef<JSVal> & obj,NG::NavigationBarOptions & options)84 void ParseBarOptions(const JSRef<JSVal>& obj, NG::NavigationBarOptions& options)
85 {
86     options.paddingStart.reset();
87     options.paddingEnd.reset();
88     options.barStyle.reset();
89     if (!obj->IsObject()) {
90         return;
91     }
92     auto optObj = JSRef<JSObject>::Cast(obj);
93     auto barStyleProperty = optObj->GetProperty(BAR_STYLE_PROPERTY);
94     if (barStyleProperty->IsNumber()) {
95         auto barStyle = barStyleProperty->ToNumber<int32_t>();
96         if (barStyle >= static_cast<int32_t>(NG::BarStyle::STANDARD) &&
97             barStyle <= static_cast<int32_t>(NG::BarStyle::SAFE_AREA_PADDING)) {
98             options.barStyle = static_cast<NG::BarStyle>(barStyle);
99         } else {
100             options.barStyle = NG::BarStyle::STANDARD;
101         }
102     }
103     CalcDimension paddingStart;
104     if (JSViewAbstract::ParseLengthMetricsToDimension(optObj->GetProperty(PADDING_START_PROPERTY), paddingStart)) {
105         options.paddingStart = paddingStart;
106     }
107     CalcDimension paddingEnd;
108     if (JSViewAbstract::ParseLengthMetricsToDimension(optObj->GetProperty(PADDING_END_PROPERTY), paddingEnd)) {
109         options.paddingEnd = paddingEnd;
110     }
111 }
112 
ParseTextOptions(const JSCallbackInfo & info,const JSRef<JSVal> & obj,NG::NavigationTextOptions & options)113 void ParseTextOptions(const JSCallbackInfo& info, const JSRef<JSVal>& obj, NG::NavigationTextOptions& options)
114 {
115     options.Reset();
116     if (!obj->IsObject()) {
117         return;
118     }
119     auto optObj = JSRef<JSObject>::Cast(obj);
120     auto mainTitleModifierProperty = optObj->GetProperty(MAIN_TITLE_MODIFIER);
121     auto subTitleModifierProperty = optObj->GetProperty(SUB_TITLE_MODIFIER);
122     JSViewAbstract::SetTextStyleApply(info, options.mainTitleApplyFunc, mainTitleModifierProperty);
123     JSViewAbstract::SetTextStyleApply(info, options.subTitleApplyFunc, subTitleModifierProperty);
124 }
125 
ParseToolBarItemAction(const WeakPtr<NG::FrameNode> & targetNode,const JSCallbackInfo & info,const JSRef<JSObject> & itemObject,NG::BarItem & toolBarItem)126 void ParseToolBarItemAction(const WeakPtr<NG::FrameNode>& targetNode,
127     const JSCallbackInfo& info, const JSRef<JSObject>& itemObject, NG::BarItem& toolBarItem)
128 {
129     auto itemActionValue = itemObject->GetProperty("action");
130     if (!itemActionValue->IsFunction()) {
131         return;
132     }
133 
134     RefPtr<JsFunction> onClickFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(itemActionValue));
135     auto onItemClick = [execCtx = info.GetExecutionContext(), func = std::move(onClickFunc),
136                             node = targetNode]() {
137         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
138         if (func) {
139             PipelineContext::SetCallBackNode(node);
140             func->ExecuteJS();
141         }
142     };
143     toolBarItem.action = onItemClick;
144 }
145 }
146 
ParseToolbarItemsConfiguration(const WeakPtr<NG::FrameNode> & targetNode,const JSCallbackInfo & info,const JSRef<JSArray> & jsArray,std::vector<NG::BarItem> & items)147 void JSNavigationUtils::ParseToolbarItemsConfiguration(const WeakPtr<NG::FrameNode>& targetNode,
148     const JSCallbackInfo& info, const JSRef<JSArray>& jsArray, std::vector<NG::BarItem>& items)
149 {
150     auto length = jsArray->Length();
151     for (size_t i = 0; i < length; i++) {
152         auto item = jsArray->GetValueAt(i);
153         if (!item->IsObject()) {
154             continue;
155         }
156 
157         NG::BarItem toolBarItem;
158         std::string text;
159         auto itemObject = JSRef<JSObject>::Cast(item);
160         auto itemValueObject = itemObject->GetProperty("value");
161         if (JSViewAbstract::ParseJsString(itemValueObject, text)) {
162             toolBarItem.text = text;
163         }
164 
165         ParseToolBarItemAction(targetNode, info, itemObject, toolBarItem);
166 
167         auto itemStatusValue = itemObject->GetProperty("status");
168         if (itemStatusValue->IsNumber()) {
169             toolBarItem.status = static_cast<NG::NavToolbarItemStatus>(itemStatusValue->ToNumber<int32_t>());
170         }
171         ParseSymbolAndIcon(info, toolBarItem, itemObject);
172         items.push_back(toolBarItem);
173     }
174 }
175 
ParseTitleBarOptions(const JSCallbackInfo & info,bool needSetDefaultValue,NG::NavigationTitlebarOptions & options)176 void JSNavigationUtils::ParseTitleBarOptions(
177     const JSCallbackInfo& info, bool needSetDefaultValue, NG::NavigationTitlebarOptions& options)
178 {
179     if (needSetDefaultValue) {
180         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
181             auto pipelineContext = PipelineBase::GetCurrentContext();
182             CHECK_NULL_VOID(pipelineContext);
183             auto theme = pipelineContext->GetTheme<NavigationBarTheme>();
184             CHECK_NULL_VOID(theme);
185             auto blurStyle = static_cast<BlurStyle>(theme->GetTitlebarBackgroundBlurStyle());
186             if (blurStyle != BlurStyle::NO_MATERIAL) {
187                 options.bgOptions.blurStyle = blurStyle;
188                 options.bgOptions.color = Color::TRANSPARENT;
189             }
190         }
191     }
192 
193     if (info.Length() > 1) {
194         if (!info[1]->IsObject()) {
195             return;
196         }
197         ParseBackgroundOptions(info[1], options.bgOptions);
198         ParseBarOptions(info[1], options.brOptions);
199         ParseTextOptions(info, info[1], options.textOptions);
200         JSRef<JSObject> jsObjOption = JSRef<JSObject>::Cast(info[1]);
201         auto enableHoverModeProperty = jsObjOption->GetProperty("enableHoverMode");
202         if (enableHoverModeProperty->IsBoolean()) {
203             options.enableHoverMode = enableHoverModeProperty->ToBoolean();
204         }
205     }
206 }
207 
ParseToolbarOptions(const JSCallbackInfo & info,NG::NavigationToolbarOptions & options)208 void JSNavigationUtils::ParseToolbarOptions(const JSCallbackInfo& info, NG::NavigationToolbarOptions& options)
209 {
210     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
211         auto pipelineContext = PipelineBase::GetCurrentContext();
212         CHECK_NULL_VOID(pipelineContext);
213         auto theme = pipelineContext->GetTheme<NavigationBarTheme>();
214         CHECK_NULL_VOID(theme);
215         auto blurStyle = static_cast<BlurStyle>(theme->GetToolbarBackgroundBlurStyle());
216         if (blurStyle != BlurStyle::NO_MATERIAL) {
217             options.bgOptions.blurStyle = blurStyle;
218             options.bgOptions.color = Color::TRANSPARENT;
219         }
220     }
221     if (info.Length() > 1) {
222         ParseBackgroundOptions(info[1], options.bgOptions);
223         ParseBarOptions(info[1], options.brOptions);
224     }
225 }
226 
ParseBarItems(const WeakPtr<NG::FrameNode> & targetNode,const JSCallbackInfo & info,const JSRef<JSArray> & jsArray,std::vector<NG::BarItem> & items)227 void JSNavigationUtils::ParseBarItems(const WeakPtr<NG::FrameNode>& targetNode,
228     const JSCallbackInfo& info, const JSRef<JSArray>& jsArray, std::vector<NG::BarItem>& items)
229 {
230     auto length = jsArray->Length();
231     for (size_t i = 0; i < length; i++) {
232         auto item = jsArray->GetValueAt(i);
233         if (!item->IsObject()) {
234             continue;
235         }
236         auto itemObject = JSRef<JSObject>::Cast(item);
237         NG::BarItem toolBarItem;
238         std::string value;
239         auto itemValueObject = itemObject->GetProperty("value");
240         if (JSViewAbstract::ParseJsString(itemValueObject, value)) {
241             toolBarItem.text = value;
242         }
243 
244         auto itemSymbolIconObject = itemObject->GetProperty("symbolIcon");
245         if (itemSymbolIconObject->IsObject()) {
246             std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
247             JSViewAbstract::SetSymbolOptionApply(info, iconSymbol, itemSymbolIconObject);
248             toolBarItem.iconSymbol = iconSymbol;
249         }
250         std::string icon;
251         auto itemIconObject = itemObject->GetProperty("icon");
252         if (JSViewAbstract::ParseJsMedia(itemIconObject, icon)) {
253             toolBarItem.icon = icon;
254         }
255 
256         auto itemEnabledObject = itemObject->GetProperty("isEnabled");
257         if (itemEnabledObject->IsBoolean()) {
258             toolBarItem.isEnabled = itemEnabledObject->ToBoolean();
259         }
260 
261         ParseToolBarItemAction(targetNode, info, itemObject, toolBarItem);
262         items.push_back(toolBarItem);
263     }
264 }
265 
266 } // namespace OHOS::Ace::Framework
267