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 "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_navigation_utils.h"
17
18 #include "core/components_ng/pattern/navigation/navigation_model_ng.h"
19
20 namespace OHOS::Ace::NG {
ParseBarItems(EcmaVM * vm,const Local<JSValueRef> & jsValue,std::vector<ArkUIBarItem> & items)21 void NativeNavigationUtils::ParseBarItems(
22 EcmaVM* vm, const Local<JSValueRef>& jsValue, std::vector<ArkUIBarItem>& items)
23 {
24 auto array = panda::Local<panda::ArrayRef>(jsValue);
25 auto length = array->Length(vm);
26 for (uint32_t index = 0; index < length; index++) {
27 auto item = panda::ArrayRef::GetValueAt(vm, array, index);
28 if (!item->IsObject(vm)) {
29 continue;
30 }
31 auto obj = item->ToObject(vm);
32 ArkUIBarItem menuItem;
33 std::string value;
34 auto itemValueObject = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "value"));
35 if (ArkTSUtils::ParseJsString(vm, itemValueObject, value)) {
36 menuItem.text.isSet = 1;
37 menuItem.text.value = new char[value.length() + 1];
38 DeepCopyStringValue(menuItem.text.value, value.length() + 1, value);
39 }
40 std::string icon;
41 auto itemIconObject = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "icon"));
42 if (ArkTSUtils::ParseJsMedia(vm, itemIconObject, icon)) {
43 menuItem.icon.isSet = 1;
44 menuItem.icon.value = new char[icon.length() + 1];
45 DeepCopyStringValue(menuItem.icon.value, icon.length() + 1, icon);
46 }
47 auto itemEnabledObject = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "isEnabled"));
48 if (itemEnabledObject->IsBoolean()) {
49 menuItem.isEnable = { 1, itemEnabledObject->ToBoolean(vm)->Value() };
50 }
51 items.push_back(menuItem);
52 }
53 }
54
ParseTitleOptions(const EcmaVM * vm,const Local<JSValueRef> & jsValue,ArkUINavigationTitlebarOptions & options)55 void NativeNavigationUtils::ParseTitleOptions(const EcmaVM* vm, const Local<JSValueRef>& jsValue,
56 ArkUINavigationTitlebarOptions& options)
57 {
58 auto obj = jsValue->ToObject(vm);
59 auto colorProperty = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "backgroundColor"));
60 Color color;
61 if (ArkTSUtils::ParseJsColor(vm, colorProperty, color)) {
62 options.colorValue = ArkUIOptionalUint { 1, color.GetValue() };
63 }
64 auto blurProperty = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "backgroundBlurStyle"));
65 if (blurProperty->IsNumber()) {
66 auto blurStyle = blurProperty->Int32Value(vm);
67 if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
68 blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
69 options.blurStyle = ArkUIOptionalInt { 1, blurStyle };
70 }
71 }
72 auto barStyleProperty = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "barStyle"));
73 if (barStyleProperty->IsNumber()) {
74 auto barStyle = barStyleProperty->Int32Value(vm);
75 if (barStyle >= static_cast<int32_t>(NG::BarStyle::STANDARD) &&
76 barStyle <= static_cast<int32_t>(NG::BarStyle::STACK)) {
77 options.barStyle = ArkUIOptionalInt { 1, barStyle };
78 } else {
79 options.barStyle = ArkUIOptionalInt { 1, static_cast<int32_t>(NG::BarStyle::STANDARD) };
80 }
81 }
82 CalcDimension paddingStart;
83 auto paddingStartProperty = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "paddingStart"));
84 if (ArkTSUtils::ParseJsLengthMetrics(vm, paddingStartProperty, paddingStart)) {
85 options.paddingStart.isSet = 1;
86 options.paddingStart.dimension.value = paddingStart.Value();
87 options.paddingStart.dimension.units = static_cast<int32_t>(paddingStart.Unit());
88 }
89 CalcDimension paddingEnd;
90 auto paddingEndProperty = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "paddingEnd"));
91 if (ArkTSUtils::ParseJsLengthMetrics(vm, paddingEndProperty, paddingEnd)) {
92 options.paddingEnd.isSet = 1;
93 options.paddingEnd.dimension.value = paddingEnd.Value();
94 options.paddingEnd.dimension.units = static_cast<int32_t>(paddingEnd.Unit());
95 }
96 auto enableHoverModeProperty = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "enableHoverMode"));
97 if (enableHoverModeProperty->IsBoolean()) {
98 options.enableHoverMode.isSet = 1;
99 options.enableHoverMode.value = enableHoverModeProperty->ToBoolean(vm)->Value();
100 }
101 }
102
ParseAndSendFunctionParam(ArkUIRuntimeCallInfo * runtimeCallInfo,const Local<JSValueRef> & jsValue,ParamSendFunction & actionSendFunc,ParamSendFunction & symbolSendFunc)103 void NativeNavigationUtils::ParseAndSendFunctionParam(ArkUIRuntimeCallInfo* runtimeCallInfo,
104 const Local<JSValueRef>& jsValue, ParamSendFunction& actionSendFunc, ParamSendFunction& symbolSendFunc)
105 {
106 EcmaVM* vm = runtimeCallInfo->GetVM();
107 CHECK_NULL_VOID(vm);
108 Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(0);
109 auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
110 auto frameNode = reinterpret_cast<FrameNode*>(nativeNode);
111 CHECK_NULL_VOID(frameNode);
112 Framework::JsiCallbackInfo info = Framework::JsiCallbackInfo(runtimeCallInfo);
113 auto jsArray = Framework::JSRef<Framework::JSArray>::Cast(info[1]);
114 auto array = panda::Local<panda::ArrayRef>(jsValue);
115 auto length = array->Length(vm);
116 for (uint32_t index = 0; index < length; index++) {
117 auto item = panda::ArrayRef::GetValueAt(vm, array, index);
118 if (!item->IsObject(vm)) {
119 continue;
120 }
121 auto obj = item->ToObject(vm);
122 auto itemSymbolIconObject = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "symbolIcon"));
123 if (itemSymbolIconObject->IsObject(vm)) {
124 std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
125 auto jsItem = jsArray->GetValueAt(index);
126 auto jsItemObject = Framework::JSRef<Framework::JSObject>::Cast(jsItem);
127 auto jsItemSymbolIconObject = jsItemObject->GetProperty("symbolIcon");
128 Framework::JSViewAbstract::SetSymbolOptionApply(runtimeCallInfo, iconSymbol, jsItemSymbolIconObject);
129 symbolSendFunc(nativeNode, reinterpret_cast<void*>(&iconSymbol), index);
130 }
131 auto itemActionValue = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "action"));
132 if (itemActionValue->IsFunction(vm)) {
133 panda::Local<panda::FunctionRef> func = itemActionValue->ToObject(vm);
134 std::function<void(void)> onItemClick = [vm, frameNode, func = panda::CopyableGlobal(vm, func)] () {
135 panda::LocalScope pandaScope(vm);
136 panda::TryCatch trycatch(vm);
137 PipelineContext::SetCallBackNode(AceType::WeakClaim(frameNode));
138 func->Call(vm, func.ToLocal(), nullptr, 0);
139 };
140 actionSendFunc(nativeNode, reinterpret_cast<void*>(&onItemClick), index);
141 }
142 }
143 }
144
DeepCopyStringValue(char * des,uint32_t desLength,const std::string & src)145 void NativeNavigationUtils::DeepCopyStringValue(char* des, uint32_t desLength, const std::string& src)
146 {
147 if (des == nullptr || desLength == 0) {
148 TAG_LOGW(AceLogTag::ACE_NAVIGATION, "destination char space allocated failed");
149 return;
150 }
151 if (src.length() == 0) {
152 des[0] = '\0';
153 return;
154 }
155 auto copyedSize = src.copy(des, desLength - 1 < src.length() ? desLength - 1 : src.length());
156 if (copyedSize == 0) {
157 TAG_LOGW(AceLogTag::ACE_NAVIGATION, "copy string to destination char failed");
158 }
159 des[copyedSize] = '\0';
160 }
161 } // namespace OHOS::Ace::NG