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 "interfaces/napi/kits/utils/napi_utils.h"
17
18 #include "bridge/common/utils/engine_helper.h"
19 #include "core/components_ng/pattern/overlay/level_order.h"
20
21 namespace OHOS::Ace::Napi {
ParseFrameNode(napi_env env,napi_callback_info info)22 static NG::FrameNode* ParseFrameNode(napi_env env, napi_callback_info info)
23 {
24 size_t argc = 1;
25 napi_value argv[2] = { nullptr };
26 napi_value thisVar = nullptr;
27 void* data = nullptr;
28 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
29 NAPI_ASSERT(env, argc >= 1, "wrong number of argument\n");
30
31 napi_value nodePtr = nullptr;
32 NAPI_CALL(env, napi_get_named_property(env, argv[0], "nodePtr_", &nodePtr));
33 napi_valuetype valueType = napi_undefined;
34 napi_typeof(env, nodePtr, &valueType);
35 NG::UINode* uiNode = nullptr;
36 if (valueType == napi_external) {
37 NAPI_CALL(env, napi_get_value_external(env, nodePtr, (void**)&uiNode));
38 }
39 CHECK_NULL_RETURN(uiNode, nullptr);
40 return reinterpret_cast<NG::FrameNode*>(uiNode);
41 }
42
JSAddFrameNode(napi_env env,napi_callback_info info)43 static napi_value JSAddFrameNode(napi_env env, napi_callback_info info)
44 {
45 NG::FrameNode* frameNode = ParseFrameNode(env, info);
46 CHECK_NULL_RETURN(frameNode, nullptr);
47 size_t argc = 2;
48 napi_value argv[2] = { nullptr };
49 napi_value thisVar = nullptr;
50 void* data = nullptr;
51 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, &data));
52 auto delegate = EngineHelper::GetCurrentDelegateSafely();
53 if (!delegate) {
54 NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
55 return nullptr;
56 }
57 if (argc == 1) {
58 delegate->AddFrameNodeToOverlay(AceType::Claim(frameNode));
59 } else {
60 napi_valuetype valueType = napi_undefined;
61 napi_typeof(env, argv[1], &valueType);
62 if (valueType == napi_number) {
63 int32_t index = 0;
64 napi_get_value_int32(env, argv[1], &index);
65 delegate->AddFrameNodeToOverlay(AceType::Claim(frameNode), index);
66 } else {
67 NapiThrow(env, "the second paramter is not number.", ERROR_CODE_PARAM_INVALID);
68 return nullptr;
69 }
70 }
71 return nullptr;
72 }
73
ParseLevelOrder(napi_env env,napi_value value)74 static std::optional<double> ParseLevelOrder(napi_env env, napi_value value)
75 {
76 napi_valuetype valueType = napi_undefined;
77 napi_typeof(env, value, &valueType);
78 if (valueType != napi_object) {
79 return std::nullopt;
80 }
81
82 NG::LevelOrder* levelOrder = nullptr;
83 napi_status status = napi_unwrap(env, value, reinterpret_cast<void**>(&levelOrder));
84 if (status != napi_ok || !levelOrder) {
85 return std::nullopt;
86 }
87
88 double order = levelOrder->GetOrder();
89 return std::make_optional(order);
90 }
91
JSAddFrameNodeWithOrder(napi_env env,napi_callback_info info)92 static napi_value JSAddFrameNodeWithOrder(napi_env env, napi_callback_info info)
93 {
94 NG::FrameNode* frameNode = ParseFrameNode(env, info);
95 CHECK_NULL_RETURN(frameNode, nullptr);
96
97 auto delegate = EngineHelper::GetCurrentDelegateSafely();
98 if (!delegate) {
99 return nullptr;
100 }
101
102 size_t argc = 2;
103 napi_value argv[2] = { nullptr };
104 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
105 std::optional<double> levelOrder = std::nullopt;
106 if (argc > 1) {
107 levelOrder = ParseLevelOrder(env, argv[1]);
108 }
109
110 delegate->AddFrameNodeWithOrder(AceType::Claim(frameNode), levelOrder);
111 return nullptr;
112 }
113
JSRemoveFrameNode(napi_env env,napi_callback_info info)114 static napi_value JSRemoveFrameNode(napi_env env, napi_callback_info info)
115 {
116 NG::FrameNode* frameNode = ParseFrameNode(env, info);
117 CHECK_NULL_RETURN(frameNode, nullptr);
118 auto delegate = EngineHelper::GetCurrentDelegateSafely();
119 if (!delegate) {
120 NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
121 return nullptr;
122 }
123 delegate->RemoveFrameNodeOnOverlay(AceType::Claim(frameNode));
124 return nullptr;
125 }
126
JSShowNode(napi_env env,napi_callback_info info)127 static napi_value JSShowNode(napi_env env, napi_callback_info info)
128 {
129 NG::FrameNode* frameNode = ParseFrameNode(env, info);
130 CHECK_NULL_RETURN(frameNode, nullptr);
131 auto delegate = EngineHelper::GetCurrentDelegateSafely();
132 if (!delegate) {
133 NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
134 return nullptr;
135 }
136 delegate->ShowNodeOnOverlay(AceType::Claim(frameNode));
137 return nullptr;
138 }
139
JSHideNode(napi_env env,napi_callback_info info)140 static napi_value JSHideNode(napi_env env, napi_callback_info info)
141 {
142 NG::FrameNode* frameNode = ParseFrameNode(env, info);
143 CHECK_NULL_RETURN(frameNode, nullptr);
144 auto delegate = EngineHelper::GetCurrentDelegateSafely();
145 if (!delegate) {
146 NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
147 return nullptr;
148 }
149 delegate->HideNodeOnOverlay(AceType::Claim(frameNode));
150 return nullptr;
151 }
152
JSShowAllFrameNodes(napi_env env,napi_callback_info info)153 static napi_value JSShowAllFrameNodes(napi_env env, napi_callback_info info)
154 {
155 auto delegate = EngineHelper::GetCurrentDelegateSafely();
156 if (!delegate) {
157 NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
158 return nullptr;
159 }
160 delegate->ShowAllNodesOnOverlay();
161 return nullptr;
162 }
163
JSHideAllFrameNodes(napi_env env,napi_callback_info info)164 static napi_value JSHideAllFrameNodes(napi_env env, napi_callback_info info)
165 {
166 auto delegate = EngineHelper::GetCurrentDelegateSafely();
167 if (!delegate) {
168 NapiThrow(env, "UI execution context not found.", ERROR_CODE_INTERNAL_ERROR);
169 return nullptr;
170 }
171 delegate->HideAllNodesOnOverlay();
172 return nullptr;
173 }
174
JSSetOverlayManagerOptions(napi_env env,napi_callback_info info)175 static napi_value JSSetOverlayManagerOptions(napi_env env, napi_callback_info info)
176 {
177 size_t argc = 1;
178 napi_value argv = nullptr;
179 napi_value thisVar = nullptr;
180 void* data = nullptr;
181 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, &thisVar, &data));
182 NAPI_ASSERT(env, argc >= 1, "wrong number of argument\n");
183
184 auto overlayInfo = NG::OverlayManagerInfo {
185 .renderRootOverlay = true,
186 .enableBackPressedEvent = false,
187 };
188 napi_value renderRootOverlayNApi = nullptr;
189 napi_value enableBackPressedEventNApi = nullptr;
190 napi_valuetype valueType = napi_undefined;
191 napi_typeof(env, argv, &valueType);
192 if (valueType == napi_object) {
193 napi_get_named_property(env, argv, "renderRootOverlay", &renderRootOverlayNApi);
194 napi_get_named_property(env, argv, "enableBackPressedEvent", &enableBackPressedEventNApi);
195 napi_get_value_bool(env, renderRootOverlayNApi, &overlayInfo.renderRootOverlay);
196 napi_get_value_bool(env, enableBackPressedEventNApi, &overlayInfo.enableBackPressedEvent);
197 } else if (valueType != napi_undefined && valueType != napi_null) {
198 NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
199 return nullptr;
200 }
201
202 napi_value result = nullptr;
203 napi_get_boolean(env, false, &result);
204 auto delegate = EngineHelper::GetCurrentDelegateSafely();
205 if (!delegate) {
206 return result;
207 }
208 if (delegate->SetOverlayManagerOptions(overlayInfo)) {
209 napi_get_boolean(env, true, &result);
210 return result;
211 }
212 return result;
213 }
214
JSGetOverlayManagerOptions(napi_env env,napi_callback_info info)215 static napi_value JSGetOverlayManagerOptions(napi_env env, napi_callback_info info)
216 {
217 napi_value result = nullptr;
218 napi_create_object(env, &result);
219 auto delegate = EngineHelper::GetCurrentDelegateSafely();
220 if (!delegate) {
221 return result;
222 }
223 std::optional<NG::OverlayManagerInfo> options = delegate->GetOverlayManagerOptions();
224 if (options.has_value()) {
225 napi_value renderRootOverlay = nullptr;
226 napi_get_boolean(env, options.value().renderRootOverlay, &renderRootOverlay);
227 napi_set_named_property(env, result, "renderRootOverlay", renderRootOverlay);
228 }
229 return result;
230 }
231
OverlayManagerExport(napi_env env,napi_value exports)232 static napi_value OverlayManagerExport(napi_env env, napi_value exports)
233 {
234 napi_property_descriptor overlayManagerDesc[] = {
235 DECLARE_NAPI_FUNCTION("addFrameNode", JSAddFrameNode),
236 DECLARE_NAPI_FUNCTION("addFrameNodeWithOrder", JSAddFrameNodeWithOrder),
237 DECLARE_NAPI_FUNCTION("removeFrameNode", JSRemoveFrameNode),
238 DECLARE_NAPI_FUNCTION("showNode", JSShowNode),
239 DECLARE_NAPI_FUNCTION("hideNode", JSHideNode),
240 DECLARE_NAPI_FUNCTION("showAllFrameNodes", JSShowAllFrameNodes),
241 DECLARE_NAPI_FUNCTION("hideAllFrameNodes", JSHideAllFrameNodes),
242 DECLARE_NAPI_FUNCTION("setOverlayManagerOptions", JSSetOverlayManagerOptions),
243 DECLARE_NAPI_FUNCTION("getOverlayManagerOptions", JSGetOverlayManagerOptions)
244 };
245 NAPI_CALL(env, napi_define_properties(
246 env, exports, sizeof(overlayManagerDesc) / sizeof(overlayManagerDesc[0]), overlayManagerDesc));
247 return exports;
248 }
249
250 static napi_module overlayManagerModule = {
251 .nm_version = 1,
252 .nm_flags = 0,
253 .nm_filename = nullptr,
254 .nm_register_func = OverlayManagerExport,
255 .nm_modname = "overlay",
256 .nm_priv = ((void*)0),
257 .reserved = { 0 },
258 };
259
OverlayRegister()260 extern "C" __attribute__((constructor)) void OverlayRegister()
261 {
262 napi_module_register(&overlayManagerModule);
263 }
264 } // namespace OHOS::Ace::Napi
265