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